load packages
library(ggplot2)
library(data.table)
library(stringr)
library(dplyr)
library(tidyr)
library(rprojroot)
library(vegan)
library(ggpubr)
library(rstatix)
library(cowplot)
library(wesanderson)
#library(BiocManager)
#library(ComplexHeatmap)
#library(ggridges)
set paths and filenames
### files
long_table=sprintf("%s/data/mp142_TGVG1.1_MPA4_combined_abundance_table_longform1.tsv", find_rstudio_root_file())
metadata_table=sprintf("%s/data/some_teddy_MP142_metadata2.all_samples1.delivery.csv", find_rstudio_root_file())
iphop_table=sprintf("%s/data/TGVG_database_v1.1.exemplars.iphop_genus_outputs1.filt.csv", find_rstudio_root_file())
taxonomy_table=sprintf("%s/data/TGVG_database_v1.1.VC_taxonomy_table.csv", find_rstudio_root_file())
load long table and metadata, merge
long_dt <- fread(sprintf("%s", long_table), sep = "\t", header = T) %>%
select(sampleID, rel_abundance, lineage) %>%
mutate(sampleID = as.character(sampleID),
kingdom = case_when(grepl("k__Bac", lineage) ~ "Bacteria",
grepl("k__Vir", lineage) ~ "Virus",
grepl("k__Ar", lineage) ~ "Archea",
grepl("k__Euk", lineage) ~ "Eukaryota",
TRUE ~ "other"))
meta_dt <- fread(sprintf("%s", metadata_table), sep = ",", header = T) %>%
select(-V1) %>%
mutate(sample = as.character(sample)) %>%
group_by(mask_id) %>%
filter(n() > 30) %>%
ungroup()
merge_dt <- merge(long_dt, meta_dt, by.x = "sampleID", by.y ="sample")
merge_dt %>%
group_by(mask_id) %>%
filter(grepl("Faecalibacterium_prausnitzii", lineage)) %>%
summarize(f_praus = n_distinct(sampleID)) %>%
arrange(desc(f_praus))
load iphop host prediction table
iphop_dt <- fread(sprintf("%s", iphop_table), sep = ",", header = T, col.names = c("name", "AAI", "host_lineage", "confidence", "methods")) %>%
mutate(host_genus = gsub(".*g__","g__", host_lineage),
host_family = gsub(";g__.*","", host_lineage))
tax_dt <- fread(sprintf("%s", taxonomy_table), sep = ",", header = T) %>%
select(c(name, Species))
iphop_tax_dt <- merge(iphop_dt, tax_dt, by = "name") %>%
mutate(species = gsub("s__", "", Species))
look at subject 248418
sub248418_dt <- merge_dt %>%
filter(mask_id == 248418) %>%
mutate(species = gsub(".*\\|s__", "", lineage))
sub248418_dt %>%
select(lineage, species, age_days, sampleID, rel_abundance) %>%
complete(species, age_days) %>%
filter(grepl("g__Faecalibacterium", lineage)) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
group_by(species) %>%
mutate(avg_age = mean(age_days),
species = gsub("_", " ",species),
species = gsub("\\|t", "",species)) %>%
ggplot(aes(x = age_days, y = rel_abundance,color = reorder(species, avg_age), fill = reorder(species, avg_age))) +
geom_col() +
geom_line() +
scale_fill_brewer(palette = "Dark2") +
scale_color_brewer(palette = "Dark2") +
facet_wrap(vars(reorder(species, avg_age)),
ncol = 1, strip.position = "right",
labeller = label_wrap_gen(width = 13)) +
theme_linedraw() +
theme(legend.position = "Off",
strip.text.y.right = element_text(angle = 0))
ggsave(file = "/Users/michaeltisza/mike_tisza/sandbox/phage_bacteria_specific_subjects/sub248418_faecali_bacteria1.pdf", width = 8, height = 2.8)

pal = wes_palette("FantasticFox1", 23, type = "continuous")
merge(sub248418_dt, iphop_tax_dt, by = "species") %>%
filter(host_genus == "g__Faecalibacterium") %>%
group_by(species) %>%
mutate(avg_age = mean(age_days)) %>%
complete(age_days) %>%
select(lineage, species, age_days, sampleID, rel_abundance, avg_age) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
ungroup() %>%
ggplot(aes(x = age_days, y = rel_abundance,color = reorder(species, avg_age), fill = reorder(species, avg_age))) +
geom_col() +
geom_line() +
scale_fill_manual(values = pal) +
scale_color_manual(values = pal) +
facet_wrap(vars(reorder(species, avg_age)),
ncol = 1, strip.position = "right",
labeller = label_wrap_gen(width = 13)) +
theme_bw() +
theme(legend.position = "Off",
strip.text.y.right = element_text(angle = 0))
ggsave(file = "/Users/michaeltisza/mike_tisza/sandbox/phage_bacteria_specific_subjects/sub248418_faecali_phage1.pdf", width = 8, height = 9.5)

complex heatmap
bac_fp_sub248418 <- sub248418_dt %>%
select(lineage, species, age_days, sampleID, rel_abundance) %>%
complete(species, age_days) %>%
filter(grepl("g__Faecalibacterium", lineage)) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
group_by(species) %>%
mutate(avg_age = mean(age_days),
species = gsub("_", " ",species),
species = gsub("\\|t", "",species)) %>%
ungroup()
bac_fp_sub248418$kingdom <- "Bacteria"
phage_fp_sub248418 <- merge(sub248418_dt, iphop_tax_dt, by = "species") %>%
filter(host_genus == "g__Faecalibacterium") %>%
group_by(species) %>%
mutate(avg_age = mean(age_days)) %>%
complete(age_days) %>%
select(lineage, species, age_days, sampleID, rel_abundance, avg_age) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
ungroup()
phage_fp_sub248418$kingdom <- "Virus"
sub248418_fp_all_dt <- rbind(bac_fp_sub248418, phage_fp_sub248418)
tempp <- sub248418_fp_all_dt %>%
mutate(species = gsub("Faecalibacterium", "F", species)) %>%
ggplot(aes(x = factor(age_days), y = reorder(species, desc(avg_age)),
color = kingdom, size = rel_abundance)) +
geom_point(alpha = 0.8) +
scale_color_manual(values = c("orangered", "cadetblue")) +
scale_size(name = "rel.\nabundance") +
facet_grid(vars(kingdom), scales = "free_y", space="free") +
theme_bw() +
labs(y = "SGB", x = "day of life") +
theme(strip.text.y.right = element_text(angle = 0),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
legend.position = "left")
detectp <- sub248418_fp_all_dt %>%
group_by(species, kingdom, avg_age) %>%
summarize(detected = n()) %>%
ggplot(aes(x = detected, y = reorder(species, desc(avg_age)))) +
geom_col(color = "grey10") +
facet_grid(vars(kingdom), scales = "free_y", space="free") +
theme_bw() +
labs(y = "", x = "# times\ndetected") +
theme(strip.text.y.right = element_blank(),
strip.background = element_blank(),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
axis.text.y = element_blank())
`summarise()` has grouped output by 'species', 'kingdom'. You can override using the `.groups` argument.
combp <- plot_grid(tempp, detectp, align = "h", axis = "b", rel_widths = c(20, 3))
combp


subject 202376

pal = wes_palette("FantasticFox1", 15, type = "continuous")
merge(sub202376_dt, iphop_tax_dt, by = "species") %>%
filter(host_genus == "g__Faecalibacterium") %>%
group_by(species) %>%
mutate(avg_age = mean(age_days)) %>%
complete(age_days) %>%
select(lineage, species, age_days, sampleID, rel_abundance, avg_age) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
ungroup() %>%
ggplot(aes(x = age_days, y = rel_abundance,color = reorder(species, avg_age), fill = reorder(species, avg_age))) +
geom_col() +
geom_line() +
scale_fill_manual(values = pal) +
scale_color_manual(values = pal) +
facet_wrap(vars(reorder(species, avg_age)),
ncol = 1, strip.position = "right",
labeller = label_wrap_gen(width = 13)) +
xlim(c(0,2100)) +
theme_bw() +
theme(legend.position = "Off",
strip.text.y.right = element_text(angle = 0))
ggsave(file = "/Users/michaeltisza/mike_tisza/sandbox/phage_bacteria_specific_subjects/sub202376_faecali_phage1.pdf", width = 8, height = 9.5)

sub202376_dt %>%
select(lineage, species, age_days, sampleID, rel_abundance) %>%
complete(species, age_days) %>%
filter(grepl("g__Dialister", lineage)) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
group_by(species) %>%
mutate(avg_age = mean(age_days),
species = gsub("_", " ",species),
species = gsub("\\|t", "",species)) %>%
ggplot(aes(x = age_days, y = rel_abundance,color = reorder(species, avg_age), fill = reorder(species, avg_age))) +
geom_col() +
geom_line() +
scale_fill_brewer(palette = "Dark2") +
scale_color_brewer(palette = "Dark2") +
facet_wrap(vars(reorder(species, avg_age)),
ncol = 1, strip.position = "right",
labeller = label_wrap_gen(width = 13)) +
theme_linedraw() +
xlim(c(0,2100)) +
theme(legend.position = "Off",
strip.text.y.right = element_text(angle = 0))

#ggsave(file = "/Users/michaeltisza/mike_tisza/sandbox/phage_bacteria_specific_subjects/sub202376_dialister_bacteria1.pdf", width = 8, height = 2.8)
pal = wes_palette("FantasticFox1", 15, type = "continuous")
merge(sub202376_dt, iphop_tax_dt, by = "species") %>%
filter(host_genus == "g__Dialister") %>%
group_by(species) %>%
mutate(avg_age = mean(age_days)) %>%
complete(age_days) %>%
select(lineage, species, age_days, sampleID, rel_abundance, avg_age) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
ungroup() %>%
ggplot(aes(x = age_days, y = rel_abundance,color = reorder(species, avg_age), fill = reorder(species, avg_age))) +
geom_col() +
geom_line() +
scale_fill_manual(values = pal) +
scale_color_manual(values = pal) +
facet_wrap(vars(reorder(species, avg_age)),
ncol = 1, strip.position = "right",
labeller = label_wrap_gen(width = 13)) +
xlim(c(0,2100)) +
theme_bw() +
theme(legend.position = "Off",
strip.text.y.right = element_text(angle = 0))
ggsave(file = "/Users/michaeltisza/mike_tisza/sandbox/phage_bacteria_specific_subjects/sub202376_dialister_phage1.pdf", width = 8, height = 9.5)

Alistipes


Roseburia

pal = wes_palette("FantasticFox1", 15, type = "continuous")
merge(sub202376_dt, iphop_tax_dt, by = "species") %>%
filter(host_genus == "g__Roseburia") %>%
group_by(species) %>%
mutate(avg_age = mean(age_days)) %>%
complete(age_days) %>%
select(lineage, species, age_days, sampleID, rel_abundance, avg_age) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
ungroup() %>%
ggplot(aes(x = age_days, y = rel_abundance,color = reorder(species, avg_age), fill = reorder(species, avg_age))) +
geom_col() +
geom_line() +
scale_fill_manual(values = pal) +
scale_color_manual(values = pal) +
facet_wrap(vars(reorder(species, avg_age)),
ncol = 1, strip.position = "right",
labeller = label_wrap_gen(width = 13)) +
xlim(c(0,2100)) +
theme_bw() +
theme(legend.position = "Off",
strip.text.y.right = element_text(angle = 0))
ggsave(file = "/Users/michaeltisza/mike_tisza/sandbox/phage_bacteria_specific_subjects/sub202376_Roseburia_phage1.pdf", width = 8, height = 9.5)
202376 tilemap
bac_fp_sub202376 <- sub202376_dt %>%
select(lineage, species, age_days, sampleID, rel_abundance) %>%
complete(species, age_days) %>%
filter(grepl("g__Faecalibacterium", lineage)) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
group_by(species) %>%
mutate(avg_age = mean(age_days),
species = gsub("_", " ",species),
species = gsub("\\|t", "",species)) %>%
ungroup()
bac_fp_sub202376$kingdom <- "Bacteria"
phage_fp_sub202376 <- merge(sub202376_dt, iphop_tax_dt, by = "species") %>%
filter(host_genus == "g__Faecalibacterium") %>%
group_by(species) %>%
mutate(avg_age = mean(age_days)) %>%
complete(age_days) %>%
select(lineage, species, age_days, sampleID, rel_abundance, avg_age) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
ungroup()
phage_fp_sub202376$kingdom <- "Virus"
sub202376_fp_all_dt <- rbind(bac_fp_sub202376, phage_fp_sub202376)
tempp <- sub202376_fp_all_dt %>%
mutate(species = gsub("Faecalibacterium", "F", species)) %>%
ggplot(aes(x = factor(age_days), y = reorder(species, desc(avg_age)),
color = kingdom, size = rel_abundance)) +
geom_point(alpha = 0.8) +
scale_color_manual(values = c("orangered", "cadetblue")) +
scale_size(name = "rel.\nabundance") +
facet_grid(vars(kingdom), scales = "free_y", space="free") +
theme_bw() +
labs(y = "SGB", x = "day of life") +
theme(strip.text.y.right = element_text(angle = 0),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
legend.position = "left")
detectp <- sub202376_fp_all_dt %>%
group_by(species, kingdom, avg_age) %>%
summarize(detected = n()) %>%
ggplot(aes(x = detected, y = reorder(species, desc(avg_age)))) +
geom_col() +
facet_grid(vars(kingdom), scales = "free_y", space="free") +
theme_bw() +
labs(y = "", x = "# times\ndetected") +
theme(strip.text.y.right = element_blank(),
strip.background = element_blank(),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
axis.text.y = element_blank())
`summarise()` has grouped output by 'species', 'kingdom'. You can override using the `.groups` argument.
combp <- plot_grid(tempp, detectp, align = "h", axis = "b", rel_widths = c(20, 3))
combp

check most prevalent bacteria with few other SGBs in genus
sub202376_dt %>%
filter(kingdom == "Bacteria") %>%
mutate(genus = gsub("\\|s__.*", "", lineage),
genus = gsub(".*\\|g__", "", genus)) %>%
group_by(species) %>%
mutate(detected = n()) %>%
ungroup() %>%
group_by(genus) %>%
mutate(distinct_g = n_distinct(species)) %>%
ungroup() %>%
distinct(genus, species, detected, distinct_g) %>%
arrange(distinct_g, desc(detected))
202376 tilemap
bac_fp_sub202376 <- sub202376_dt %>%
select(lineage, species, age_days, sampleID, rel_abundance) %>%
complete(species, age_days) %>%
filter(grepl("g__Flavonifractor", lineage)) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
group_by(species) %>%
mutate(avg_age = mean(age_days),
species = gsub("_", " ",species),
species = gsub("\\|t", "",species)) %>%
ungroup()
bac_fp_sub202376$kingdom <- "Bacteria"
phage_fp_sub202376 <- merge(sub202376_dt, iphop_tax_dt, by = "species") %>%
filter(host_genus == "g__Flavonifractor") %>%
group_by(species) %>%
mutate(avg_age = mean(age_days)) %>%
complete(age_days) %>%
select(lineage, species, age_days, sampleID, rel_abundance, avg_age) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
ungroup()
phage_fp_sub202376$kingdom <- "Virus"
sub202376_fp_all_dt <- rbind(bac_fp_sub202376, phage_fp_sub202376)
tempp <- sub202376_fp_all_dt %>%
mutate(species = gsub("Flavonifractor", "F", species)) %>%
ggplot(aes(x = factor(age_days), y = reorder(species, desc(avg_age)),
color = kingdom, size = rel_abundance)) +
geom_point(alpha = 0.8) +
scale_color_manual(values = c("orangered", "cadetblue")) +
scale_size(name = "rel.\nabundance") +
facet_grid(vars(kingdom), scales = "free_y", space="free") +
theme_bw() +
labs(y = "SGB", x = "day of life") +
theme(strip.text.y.right = element_text(angle = 0),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
legend.position = "left")
detectp <- sub202376_fp_all_dt %>%
group_by(species, kingdom, avg_age) %>%
summarize(detected = n()) %>%
ggplot(aes(x = detected, y = reorder(species, desc(avg_age)))) +
geom_col() +
facet_grid(vars(kingdom), scales = "free_y", space="free") +
theme_bw() +
labs(y = "", x = "# times\ndetected") +
theme(strip.text.y.right = element_blank(),
strip.background = element_blank(),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
axis.text.y = element_blank())
`summarise()` has grouped output by 'species', 'kingdom'. You can override using the `.groups` argument.
combp <- plot_grid(tempp, detectp, align = "h", axis = "b", rel_widths = c(20, 3))
combp

202376 tilemap
bac_fp_sub202376 <- sub202376_dt %>%
select(lineage, species, age_days, sampleID, rel_abundance) %>%
complete(species, age_days) %>%
filter(grepl("g__Escherichia", lineage)) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
group_by(species) %>%
mutate(avg_age = mean(age_days),
species = gsub("_", " ",species),
species = gsub("\\|t", "",species)) %>%
ungroup()
bac_fp_sub202376$kingdom <- "Bacteria"
phage_fp_sub202376 <- merge(sub202376_dt, iphop_tax_dt, by = "species") %>%
filter(host_genus == "g__Escherichia") %>%
group_by(species) %>%
mutate(avg_age = mean(age_days)) %>%
complete(age_days) %>%
select(lineage, species, age_days, sampleID, rel_abundance, avg_age) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
ungroup()
phage_fp_sub202376$kingdom <- "Virus"
sub202376_fp_all_dt <- rbind(bac_fp_sub202376, phage_fp_sub202376)
tempp <- sub202376_fp_all_dt %>%
mutate(species = gsub("Escherichia", "E", species)) %>%
ggplot(aes(x = factor(age_days), y = reorder(species, desc(avg_age)),
color = kingdom, size = rel_abundance)) +
geom_point(alpha = 0.8) +
scale_color_manual(values = c("orangered", "cadetblue")) +
scale_size(name = "rel.\nabundance") +
facet_grid(vars(kingdom), scales = "free_y", space="free") +
theme_bw() +
labs(y = "SGB", x = "day of life") +
theme(strip.text.y.right = element_text(angle = 0),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
legend.position = "left")
detectp <- sub202376_fp_all_dt %>%
group_by(species, kingdom, avg_age) %>%
summarize(detected = n()) %>%
ggplot(aes(x = detected, y = reorder(species, desc(avg_age)))) +
geom_col() +
facet_grid(vars(kingdom), scales = "free_y", space="free") +
theme_bw() +
labs(y = "", x = "# times\ndetected") +
theme(strip.text.y.right = element_blank(),
strip.background = element_blank(),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
axis.text.y = element_blank())
`summarise()` has grouped output by 'species', 'kingdom'. You can override using the `.groups` argument.
combp <- plot_grid(tempp, detectp, align = "h", axis = "b", rel_widths = c(20, 3))
combp

202376 tilemap
bac_fp_sub202376 <- sub202376_dt %>%
select(lineage, species, age_days, sampleID, rel_abundance) %>%
complete(species, age_days) %>%
filter(grepl("g__Barnesiella", lineage)) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
group_by(species) %>%
mutate(avg_age = mean(age_days),
species = gsub("_", " ",species),
species = gsub("\\|t", "",species)) %>%
ungroup()
bac_fp_sub202376$kingdom <- "Bacteria"
phage_fp_sub202376 <- merge(sub202376_dt, iphop_tax_dt, by = "species") %>%
filter(host_genus == "g__Barnesiella") %>%
group_by(species) %>%
mutate(avg_age = mean(age_days)) %>%
complete(age_days) %>%
select(lineage, species, age_days, sampleID, rel_abundance, avg_age) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
ungroup()
phage_fp_sub202376$kingdom <- "Virus"
sub202376_fp_all_dt <- rbind(bac_fp_sub202376, phage_fp_sub202376)
tempp <- sub202376_fp_all_dt %>%
mutate(species = gsub("Barnesiella", "B", species)) %>%
ggplot(aes(x = factor(age_days), y = reorder(species, desc(avg_age)),
color = kingdom, size = rel_abundance)) +
geom_point(alpha = 0.8) +
scale_color_manual(values = c("orangered", "cadetblue")) +
scale_size(name = "rel.\nabundance") +
facet_grid(vars(kingdom), scales = "free_y", space="free") +
theme_bw() +
labs(y = "SGB", x = "day of life") +
theme(strip.text.y.right = element_text(angle = 0),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
legend.position = "left")
detectp <- sub202376_fp_all_dt %>%
group_by(species, kingdom, avg_age) %>%
summarize(detected = n()) %>%
ggplot(aes(x = detected, y = reorder(species, desc(avg_age)))) +
geom_col() +
facet_grid(vars(kingdom), scales = "free_y", space="free") +
theme_bw() +
labs(y = "", x = "# times\ndetected") +
theme(strip.text.y.right = element_blank(),
strip.background = element_blank(),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
axis.text.y = element_blank())
`summarise()` has grouped output by 'species', 'kingdom'. You can override using the `.groups` argument.
combp <- plot_grid(tempp, detectp, align = "h", axis = "b", rel_widths = c(20, 3))
combp

Parabacteroides 202376 tilemap
bac_fp_sub202376 <- sub202376_dt %>%
select(lineage, species, age_days, sampleID, rel_abundance) %>%
complete(species, age_days) %>%
filter(grepl("g__Parabacteroides", lineage)) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
group_by(species) %>%
mutate(avg_age = mean(age_days),
species = gsub("_", " ",species),
species = gsub("\\|t", "",species)) %>%
ungroup()
bac_fp_sub202376$kingdom <- "Bacteria"
phage_fp_sub202376 <- merge(sub202376_dt, iphop_tax_dt, by = "species") %>%
filter(host_genus == "g__Parabacteroides") %>%
group_by(species) %>%
mutate(avg_age = mean(age_days)) %>%
complete(age_days) %>%
select(lineage, species, age_days, sampleID, rel_abundance, avg_age) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
ungroup()
phage_fp_sub202376$kingdom <- "Virus"
sub202376_fp_all_dt <- rbind(bac_fp_sub202376, phage_fp_sub202376)
tempp <- sub202376_fp_all_dt %>%
mutate(species = gsub("Parabacteroides", "P", species)) %>%
ggplot(aes(x = factor(age_days), y = reorder(species, desc(avg_age)),
color = kingdom, size = rel_abundance)) +
geom_point(alpha = 0.8) +
scale_color_manual(values = c("orangered", "cadetblue")) +
scale_size(name = "rel.\nabundance") +
facet_grid(vars(kingdom), scales = "free_y", space="free") +
theme_bw() +
labs(y = "SGB", x = "day of life") +
theme(strip.text.y.right = element_text(angle = 0),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
legend.position = "left")
detectp <- sub202376_fp_all_dt %>%
group_by(species, kingdom, avg_age) %>%
summarize(detected = n()) %>%
ggplot(aes(x = detected, y = reorder(species, desc(avg_age)))) +
geom_col() +
facet_grid(vars(kingdom), scales = "free_y", space="free") +
theme_bw() +
labs(y = "", x = "# times\ndetected") +
theme(strip.text.y.right = element_blank(),
strip.background = element_blank(),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
axis.text.y = element_blank())
`summarise()` has grouped output by 'species', 'kingdom'. You can override using the `.groups` argument.
combp <- plot_grid(tempp, detectp, align = "h", axis = "b", rel_widths = c(20, 3))
combp

Bacteroides 202376 tilemap
bac_fp_sub202376 <- sub202376_dt %>%
select(lineage, species, age_days, sampleID, rel_abundance) %>%
complete(species, age_days) %>%
filter(grepl("g__Blautia", lineage)) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
group_by(species) %>%
mutate(avg_age = mean(age_days),
species = gsub("_", " ",species),
species = gsub("\\|t", "",species)) %>%
ungroup()
bac_fp_sub202376$kingdom <- "Bacteria"
phage_fp_sub202376 <- merge(sub202376_dt, iphop_tax_dt, by = "species") %>%
filter(host_genus == "g__Blautia") %>%
group_by(species) %>%
mutate(avg_age = mean(age_days)) %>%
complete(age_days) %>%
select(lineage, species, age_days, sampleID, rel_abundance, avg_age) %>%
mutate(rel_abundance = ifelse(is.na(rel_abundance), 0, rel_abundance)) %>%
ungroup()
phage_fp_sub202376$kingdom <- "Virus"
sub202376_fp_all_dt <- rbind(bac_fp_sub202376, phage_fp_sub202376)
tempp <- sub202376_fp_all_dt %>%
mutate(species = gsub("Veillonella", "V", species)) %>%
ggplot(aes(x = factor(age_days), y = reorder(species, desc(avg_age)),
color = kingdom, size = rel_abundance)) +
geom_point(alpha = 0.8) +
scale_color_manual(values = c("orangered", "cadetblue")) +
scale_size(name = "rel.\nabundance") +
facet_grid(vars(kingdom), scales = "free_y", space="free") +
theme_bw() +
labs(y = "SGB", x = "day of life") +
theme(strip.text.y.right = element_text(angle = 0),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
legend.position = "left")
detectp <- sub202376_fp_all_dt %>%
group_by(species, kingdom, avg_age) %>%
summarize(detected = n()) %>%
ggplot(aes(x = detected, y = reorder(species, desc(avg_age)))) +
geom_col() +
facet_grid(vars(kingdom), scales = "free_y", space="free") +
theme_bw() +
labs(y = "", x = "# times\ndetected") +
theme(strip.text.y.right = element_blank(),
strip.background = element_blank(),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
axis.text.y = element_blank())
`summarise()` has grouped output by 'species', 'kingdom'. You can override using the `.groups` argument.
combp <- plot_grid(tempp, detectp, align = "h", axis = "b", rel_widths = c(20, 3))
combp

LS0tCnRpdGxlOiAibG9uZ3Rlcm0gYmFjdGVyaWEgYW5kIHRoZWlyIHBoYWdlcyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQpsb2FkIHBhY2thZ2VzCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5cikKbGlicmFyeShycHJvanJvb3QpCmxpYnJhcnkodmVnYW4pCmxpYnJhcnkoZ2dwdWJyKQpsaWJyYXJ5KHJzdGF0aXgpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeSh3ZXNhbmRlcnNvbikKI2xpYnJhcnkoQmlvY01hbmFnZXIpCiNsaWJyYXJ5KENvbXBsZXhIZWF0bWFwKQojbGlicmFyeShnZ3JpZGdlcykKYGBgCgoKc2V0IHBhdGhzIGFuZCBmaWxlbmFtZXMKCmBgYHtyfQojIyMgZmlsZXMKbG9uZ190YWJsZT1zcHJpbnRmKCIlcy9kYXRhL21wMTQyX1RHVkcxLjFfTVBBNF9jb21iaW5lZF9hYnVuZGFuY2VfdGFibGVfbG9uZ2Zvcm0xLnRzdiIsIGZpbmRfcnN0dWRpb19yb290X2ZpbGUoKSkKbWV0YWRhdGFfdGFibGU9c3ByaW50ZigiJXMvZGF0YS9zb21lX3RlZGR5X01QMTQyX21ldGFkYXRhMi5hbGxfc2FtcGxlczEuZGVsaXZlcnkuY3N2IiwgZmluZF9yc3R1ZGlvX3Jvb3RfZmlsZSgpKQppcGhvcF90YWJsZT1zcHJpbnRmKCIlcy9kYXRhL1RHVkdfZGF0YWJhc2VfdjEuMS5leGVtcGxhcnMuaXBob3BfZ2VudXNfb3V0cHV0czEuZmlsdC5jc3YiLCBmaW5kX3JzdHVkaW9fcm9vdF9maWxlKCkpCnRheG9ub215X3RhYmxlPXNwcmludGYoIiVzL2RhdGEvVEdWR19kYXRhYmFzZV92MS4xLlZDX3RheG9ub215X3RhYmxlLmNzdiIsIGZpbmRfcnN0dWRpb19yb290X2ZpbGUoKSkKCmBgYAoKbG9hZCBsb25nIHRhYmxlIGFuZCBtZXRhZGF0YSwgbWVyZ2UKCmBgYHtyfQpsb25nX2R0IDwtIGZyZWFkKHNwcmludGYoIiVzIiwgbG9uZ190YWJsZSksIHNlcCA9ICJcdCIsIGhlYWRlciA9IFQpICU+JQogIHNlbGVjdChzYW1wbGVJRCwgcmVsX2FidW5kYW5jZSwgbGluZWFnZSkgJT4lCiAgbXV0YXRlKHNhbXBsZUlEID0gYXMuY2hhcmFjdGVyKHNhbXBsZUlEKSwKICAgICAgICAga2luZ2RvbSA9IGNhc2Vfd2hlbihncmVwbCgia19fQmFjIiwgbGluZWFnZSkgfiAiQmFjdGVyaWEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmVwbCgia19fVmlyIiwgbGluZWFnZSkgfiAiVmlydXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJrX19BciIsIGxpbmVhZ2UpIH4gIkFyY2hlYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoImtfX0V1ayIsIGxpbmVhZ2UpIH4gIkV1a2FyeW90YSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJvdGhlciIpKQoKbWV0YV9kdCA8LSBmcmVhZChzcHJpbnRmKCIlcyIsIG1ldGFkYXRhX3RhYmxlKSwgc2VwID0gIiwiLCBoZWFkZXIgPSBUKSAlPiUKICBzZWxlY3QoLVYxKSAlPiUKICBtdXRhdGUoc2FtcGxlID0gYXMuY2hhcmFjdGVyKHNhbXBsZSkpICU+JQogIGdyb3VwX2J5KG1hc2tfaWQpICU+JQogIGZpbHRlcihuKCkgPiAzMCkgJT4lCiAgdW5ncm91cCgpCgptZXJnZV9kdCA8LSBtZXJnZShsb25nX2R0LCBtZXRhX2R0LCBieS54ID0gInNhbXBsZUlEIiwgYnkueSA9InNhbXBsZSIpCgpgYGAKCgpgYGB7cn0KbWVyZ2VfZHQgJT4lCiAgZ3JvdXBfYnkobWFza19pZCkgJT4lCiAgZmlsdGVyKGdyZXBsKCJGYWVjYWxpYmFjdGVyaXVtX3ByYXVzbml0emlpIiwgbGluZWFnZSkpICU+JQogIHN1bW1hcml6ZShmX3ByYXVzID0gbl9kaXN0aW5jdChzYW1wbGVJRCkpICU+JQogIGFycmFuZ2UoZGVzYyhmX3ByYXVzKSkKYGBgCgpsb2FkIGlwaG9wIGhvc3QgcHJlZGljdGlvbiB0YWJsZQpgYGB7cn0KaXBob3BfZHQgPC0gZnJlYWQoc3ByaW50ZigiJXMiLCBpcGhvcF90YWJsZSksIHNlcCA9ICIsIiwgaGVhZGVyID0gVCwgY29sLm5hbWVzID0gYygibmFtZSIsICJBQUkiLCAiaG9zdF9saW5lYWdlIiwgImNvbmZpZGVuY2UiLCAibWV0aG9kcyIpKSAlPiUKICBtdXRhdGUoaG9zdF9nZW51cyA9IGdzdWIoIi4qZ19fIiwiZ19fIiwgaG9zdF9saW5lYWdlKSwKICAgICAgICAgaG9zdF9mYW1pbHkgPSBnc3ViKCI7Z19fLioiLCIiLCBob3N0X2xpbmVhZ2UpKQoKdGF4X2R0IDwtIGZyZWFkKHNwcmludGYoIiVzIiwgdGF4b25vbXlfdGFibGUpLCBzZXAgPSAiLCIsIGhlYWRlciA9IFQpICU+JQogIHNlbGVjdChjKG5hbWUsIFNwZWNpZXMpKQoKaXBob3BfdGF4X2R0IDwtIG1lcmdlKGlwaG9wX2R0LCB0YXhfZHQsIGJ5ID0gIm5hbWUiKSAlPiUKICBtdXRhdGUoc3BlY2llcyA9IGdzdWIoInNfXyIsICIiLCBTcGVjaWVzKSkKYGBgCgoKbG9vayBhdCBzdWJqZWN0IDI0ODQxOApgYGB7cn0Kc3ViMjQ4NDE4X2R0IDwtIG1lcmdlX2R0ICU+JQogIGZpbHRlcihtYXNrX2lkID09IDI0ODQxOCkgJT4lCiAgbXV0YXRlKHNwZWNpZXMgPSBnc3ViKCIuKlxcfHNfXyIsICIiLCBsaW5lYWdlKSkKCnN1YjI0ODQxOF9kdCAlPiUKICBzZWxlY3QobGluZWFnZSwgc3BlY2llcywgYWdlX2RheXMsIHNhbXBsZUlELCByZWxfYWJ1bmRhbmNlKSAlPiUKICBjb21wbGV0ZShzcGVjaWVzLCBhZ2VfZGF5cykgJT4lCiAgZmlsdGVyKGdyZXBsKCJnX19GYWVjYWxpYmFjdGVyaXVtIiwgbGluZWFnZSkpICU+JQogIG11dGF0ZShyZWxfYWJ1bmRhbmNlID0gaWZlbHNlKGlzLm5hKHJlbF9hYnVuZGFuY2UpLCAwLCByZWxfYWJ1bmRhbmNlKSkgJT4lCiAgZ3JvdXBfYnkoc3BlY2llcykgJT4lCiAgbXV0YXRlKGF2Z19hZ2UgPSBtZWFuKGFnZV9kYXlzKSwKICAgICAgICAgc3BlY2llcyA9IGdzdWIoIl8iLCAiICIsc3BlY2llcyksCiAgICAgICAgIHNwZWNpZXMgPSBnc3ViKCJcXHx0IiwgIiIsc3BlY2llcykpICU+JQogIGdncGxvdChhZXMoeCA9IGFnZV9kYXlzLCB5ID0gcmVsX2FidW5kYW5jZSxjb2xvciA9IHJlb3JkZXIoc3BlY2llcywgYXZnX2FnZSksIGZpbGwgPSByZW9yZGVyKHNwZWNpZXMsIGF2Z19hZ2UpKSkgKwogIGdlb21fY29sKCkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikgKwogIGZhY2V0X3dyYXAodmFycyhyZW9yZGVyKHNwZWNpZXMsIGF2Z19hZ2UpKSwgIAogICAgICAgICAgICAgbmNvbCA9IDEsIHN0cmlwLnBvc2l0aW9uID0gInJpZ2h0IiwgCiAgICAgICAgICAgICBsYWJlbGxlciA9IGxhYmVsX3dyYXBfZ2VuKHdpZHRoID0gMTMpKSArCiAgdGhlbWVfbGluZWRyYXcoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIk9mZiIsCiAgICAgICAgc3RyaXAudGV4dC55LnJpZ2h0ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCkpCgpnZ3NhdmUoZmlsZSA9ICIvVXNlcnMvbWljaGFlbHRpc3phL21pa2VfdGlzemEvc2FuZGJveC9waGFnZV9iYWN0ZXJpYV9zcGVjaWZpY19zdWJqZWN0cy9zdWIyNDg0MThfZmFlY2FsaV9iYWN0ZXJpYTEucGRmIiwgd2lkdGggPSA4LCBoZWlnaHQgPSAyLjgpCgpgYGAKCmBgYHtyfQoKcGFsID0gd2VzX3BhbGV0dGUoIkZhbnRhc3RpY0ZveDEiLCAyMywgdHlwZSA9ICJjb250aW51b3VzIikKCm1lcmdlKHN1YjI0ODQxOF9kdCwgaXBob3BfdGF4X2R0LCBieSA9ICJzcGVjaWVzIikgJT4lCiAgZmlsdGVyKGhvc3RfZ2VudXMgPT0gImdfX0ZhZWNhbGliYWN0ZXJpdW0iKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoYXZnX2FnZSA9IG1lYW4oYWdlX2RheXMpKSAlPiUKICBjb21wbGV0ZShhZ2VfZGF5cykgJT4lCiAgc2VsZWN0KGxpbmVhZ2UsIHNwZWNpZXMsIGFnZV9kYXlzLCBzYW1wbGVJRCwgcmVsX2FidW5kYW5jZSwgYXZnX2FnZSkgJT4lCiAgbXV0YXRlKHJlbF9hYnVuZGFuY2UgPSBpZmVsc2UoaXMubmEocmVsX2FidW5kYW5jZSksIDAsIHJlbF9hYnVuZGFuY2UpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gYWdlX2RheXMsIHkgPSByZWxfYWJ1bmRhbmNlLGNvbG9yID0gcmVvcmRlcihzcGVjaWVzLCBhdmdfYWdlKSwgZmlsbCA9IHJlb3JkZXIoc3BlY2llcywgYXZnX2FnZSkpKSArCiAgZ2VvbV9jb2woKSArCiAgZ2VvbV9saW5lKCkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBwYWwpICsKICBmYWNldF93cmFwKHZhcnMocmVvcmRlcihzcGVjaWVzLCBhdmdfYWdlKSksICAKICAgICAgICAgICAgIG5jb2wgPSAxLCBzdHJpcC5wb3NpdGlvbiA9ICJyaWdodCIsIAogICAgICAgICAgICAgbGFiZWxsZXIgPSBsYWJlbF93cmFwX2dlbih3aWR0aCA9IDEzKSkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJPZmYiLAogICAgICAgIHN0cmlwLnRleHQueS5yaWdodCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDApKQoKZ2dzYXZlKGZpbGUgPSAiL1VzZXJzL21pY2hhZWx0aXN6YS9taWtlX3Rpc3phL3NhbmRib3gvcGhhZ2VfYmFjdGVyaWFfc3BlY2lmaWNfc3ViamVjdHMvc3ViMjQ4NDE4X2ZhZWNhbGlfcGhhZ2UxLnBkZiIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gOS41KQoKYGBgCgpjb21wbGV4IGhlYXRtYXAKYGBge3J9CmJhY19mcF9zdWIyNDg0MTggPC0gc3ViMjQ4NDE4X2R0ICU+JQogIHNlbGVjdChsaW5lYWdlLCBzcGVjaWVzLCBhZ2VfZGF5cywgc2FtcGxlSUQsIHJlbF9hYnVuZGFuY2UpICU+JQogIGNvbXBsZXRlKHNwZWNpZXMsIGFnZV9kYXlzKSAlPiUKICBmaWx0ZXIoZ3JlcGwoImdfX0ZhZWNhbGliYWN0ZXJpdW0iLCBsaW5lYWdlKSkgJT4lCiAgbXV0YXRlKHJlbF9hYnVuZGFuY2UgPSBpZmVsc2UoaXMubmEocmVsX2FidW5kYW5jZSksIDAsIHJlbF9hYnVuZGFuY2UpKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoYXZnX2FnZSA9IG1lYW4oYWdlX2RheXMpLAogICAgICAgICBzcGVjaWVzID0gZ3N1YigiXyIsICIgIixzcGVjaWVzKSwKICAgICAgICAgc3BlY2llcyA9IGdzdWIoIlxcfHQiLCAiIixzcGVjaWVzKSkgJT4lCiAgdW5ncm91cCgpCgpiYWNfZnBfc3ViMjQ4NDE4JGtpbmdkb20gPC0gIkJhY3RlcmlhIgoKcGhhZ2VfZnBfc3ViMjQ4NDE4IDwtIG1lcmdlKHN1YjI0ODQxOF9kdCwgaXBob3BfdGF4X2R0LCBieSA9ICJzcGVjaWVzIikgJT4lCiAgZmlsdGVyKGhvc3RfZ2VudXMgPT0gImdfX0ZhZWNhbGliYWN0ZXJpdW0iKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoYXZnX2FnZSA9IG1lYW4oYWdlX2RheXMpKSAlPiUKICBjb21wbGV0ZShhZ2VfZGF5cykgJT4lCiAgc2VsZWN0KGxpbmVhZ2UsIHNwZWNpZXMsIGFnZV9kYXlzLCBzYW1wbGVJRCwgcmVsX2FidW5kYW5jZSwgYXZnX2FnZSkgJT4lCiAgbXV0YXRlKHJlbF9hYnVuZGFuY2UgPSBpZmVsc2UoaXMubmEocmVsX2FidW5kYW5jZSksIDAsIHJlbF9hYnVuZGFuY2UpKSAlPiUKICB1bmdyb3VwKCkKCnBoYWdlX2ZwX3N1YjI0ODQxOCRraW5nZG9tIDwtICJWaXJ1cyIKCnN1YjI0ODQxOF9mcF9hbGxfZHQgPC0gcmJpbmQoYmFjX2ZwX3N1YjI0ODQxOCwgcGhhZ2VfZnBfc3ViMjQ4NDE4KQoKYGBgCgoKYGBge3J9CnN1YjI0ODQxOF9mcF9hbGxfZHQgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZmFjdG9yKGFnZV9kYXlzKSwgeSA9IHJlb3JkZXIoc3BlY2llcywgYXZnX2FnZSksIAogICAgICAgICAgICAgZmlsbCA9IHJlbF9hYnVuZGFuY2UpKSArCiAgZ2VvbV90aWxlKCkgKwogIHNjYWxlX2ZpbGxfZ3JhZGllbnQobG93ID0gImNhZGV0Ymx1ZSIsIGhpZ2ggPSAiYmxhY2siKSArCiAgI2ZhY2V0X3dyYXAodmFycyhraW5nZG9tKSwgbmNvbCA9IDEsIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgZmFjZXRfZ3JpZCh2YXJzKGtpbmdkb20pLCBzY2FsZXMgPSAiZnJlZV95Iiwgc3BhY2U9ImZyZWUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoc3RyaXAudGV4dC55LnJpZ2h0ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEpKQoKdGVtcHAgPC0gc3ViMjQ4NDE4X2ZwX2FsbF9kdCAlPiUKICBtdXRhdGUoc3BlY2llcyA9IGdzdWIoIkZhZWNhbGliYWN0ZXJpdW0iLCAiRiIsIHNwZWNpZXMpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBmYWN0b3IoYWdlX2RheXMpLCB5ID0gcmVvcmRlcihzcGVjaWVzLCBkZXNjKGF2Z19hZ2UpKSwgCiAgICAgICAgICAgICBjb2xvciA9IGtpbmdkb20sIHNpemUgPSByZWxfYWJ1bmRhbmNlKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjgpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygib3JhbmdlcmVkIiwgImNhZGV0Ymx1ZSIpKSArCiAgc2NhbGVfc2l6ZShuYW1lID0gInJlbC5cbmFidW5kYW5jZSIpICsgIAogIGZhY2V0X2dyaWQodmFycyhraW5nZG9tKSwgc2NhbGVzID0gImZyZWVfeSIsIHNwYWNlPSJmcmVlIikgKwogIHRoZW1lX2J3KCkgKwogIGxhYnMoeSA9ICJTR0IiLCB4ID0gImRheSBvZiBsaWZlIikgKwogIHRoZW1lKHN0cmlwLnRleHQueS5yaWdodCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDApLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdD0xKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibGVmdCIpCgpkZXRlY3RwIDwtIHN1YjI0ODQxOF9mcF9hbGxfZHQgJT4lCiAgZ3JvdXBfYnkoc3BlY2llcywga2luZ2RvbSwgYXZnX2FnZSkgJT4lCiAgc3VtbWFyaXplKGRldGVjdGVkID0gbigpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkZXRlY3RlZCwgeSA9IHJlb3JkZXIoc3BlY2llcywgZGVzYyhhdmdfYWdlKSkpKSArCiAgZ2VvbV9jb2woY29sb3IgPSAiZ3JleTEwIikgKwogIGZhY2V0X2dyaWQodmFycyhraW5nZG9tKSwgc2NhbGVzID0gImZyZWVfeSIsIHNwYWNlPSJmcmVlIikgKwogIHRoZW1lX2J3KCkgKwogIGxhYnMoeSA9ICIiLCB4ID0gIiMgdGltZXNcbmRldGVjdGVkIikgKwogIHRoZW1lKHN0cmlwLnRleHQueS5yaWdodCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCkpCgpjb21icCA8LSBwbG90X2dyaWQodGVtcHAsIGRldGVjdHAsIGFsaWduID0gImgiLCBheGlzID0gImIiLCByZWxfd2lkdGhzID0gYygyMCwgMykpCgpjb21icAoKZ2dzYXZlKGNvbWJwLCBmaWxlID0gIi9Vc2Vycy9taWNoYWVsdGlzemEvbWlrZV90aXN6YS9zYW5kYm94L3BoYWdlX2JhY3RlcmlhX3NwZWNpZmljX3N1YmplY3RzL3N1YjI0ODQxOF9mYWVjYWxpX2JhY19waGFnZTIucGRmIiwgd2lkdGggPSA4LCBoZWlnaHQgPSA1KQoKYGBgCgoKYGBge3J9CnN1YjI0ODQxOF9mcF9hbGxfZHQgJT4lCiAgZ2dwbG90KGFlcyh4ID0gYWdlX2RheXMsIHkgPSByZW9yZGVyKHNwZWNpZXMsIGF2Z19hZ2UpLCAKICAgICAgICAgICAgIGZpbGwgPSBraW5nZG9tKSkgKwogIGdlb21fY29sKCkgKwogIGdlb21fbGluZSgpICsKICBmYWNldF9ncmlkKHZhcnMoa2luZ2RvbSwgc3BlY2llcyksIHNjYWxlcyA9ICJmcmVlX3kiLCBzcGFjZT0iZnJlZSIsCiAgICAgICAgICAgICBsYWJlbGxlciA9IGxhYmVsX3dyYXBfZ2VuKHdpZHRoID0gMTMpKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoc3RyaXAudGV4dC55LnJpZ2h0ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEpKQpgYGAKCnN1YmplY3QgMjAyMzc2CmBgYHtyfQpzdWIyMDIzNzZfZHQgPC0gbWVyZ2VfZHQgJT4lCiAgZmlsdGVyKG1hc2tfaWQgPT0gMjAyMzc2KSAlPiUKICBtdXRhdGUoc3BlY2llcyA9IGdzdWIoIi4qXFx8c19fIiwgIiIsIGxpbmVhZ2UpKQoKc3ViMjAyMzc2X2R0ICU+JQogIHNlbGVjdChsaW5lYWdlLCBzcGVjaWVzLCBhZ2VfZGF5cywgc2FtcGxlSUQsIHJlbF9hYnVuZGFuY2UpICU+JQogIGNvbXBsZXRlKHNwZWNpZXMsIGFnZV9kYXlzKSAlPiUKICBmaWx0ZXIoZ3JlcGwoImdfX0ZhZWNhbGliYWN0ZXJpdW0iLCBsaW5lYWdlKSkgJT4lCiAgbXV0YXRlKHJlbF9hYnVuZGFuY2UgPSBpZmVsc2UoaXMubmEocmVsX2FidW5kYW5jZSksIDAsIHJlbF9hYnVuZGFuY2UpKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoYXZnX2FnZSA9IG1lYW4oYWdlX2RheXMpLAogICAgICAgICBzcGVjaWVzID0gZ3N1YigiXyIsICIgIixzcGVjaWVzKSwKICAgICAgICAgc3BlY2llcyA9IGdzdWIoIlxcfHQiLCAiIixzcGVjaWVzKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gYWdlX2RheXMsIHkgPSByZWxfYWJ1bmRhbmNlLGNvbG9yID0gcmVvcmRlcihzcGVjaWVzLCBhdmdfYWdlKSwgZmlsbCA9IHJlb3JkZXIoc3BlY2llcywgYXZnX2FnZSkpKSArCiAgZ2VvbV9jb2woKSArCiAgZ2VvbV9saW5lKCkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgZmFjZXRfd3JhcCh2YXJzKHJlb3JkZXIoc3BlY2llcywgYXZnX2FnZSkpLCAgCiAgICAgICAgICAgICBuY29sID0gMSwgc3RyaXAucG9zaXRpb24gPSAicmlnaHQiLCAKICAgICAgICAgICAgIGxhYmVsbGVyID0gbGFiZWxfd3JhcF9nZW4od2lkdGggPSAxMykpICsKICB0aGVtZV9saW5lZHJhdygpICsKICB4bGltKGMoMCwyMTAwKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJPZmYiLAogICAgICAgIHN0cmlwLnRleHQueS5yaWdodCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDApKQoKZ2dzYXZlKGZpbGUgPSAiL1VzZXJzL21pY2hhZWx0aXN6YS9taWtlX3Rpc3phL3NhbmRib3gvcGhhZ2VfYmFjdGVyaWFfc3BlY2lmaWNfc3ViamVjdHMvc3ViMjAyMzc2X2ZhZWNhbGlfYmFjdGVyaWExLnBkZiIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gMi44KQoKYGBgCgpgYGB7cn0KCnBhbCA9IHdlc19wYWxldHRlKCJGYW50YXN0aWNGb3gxIiwgMTUsIHR5cGUgPSAiY29udGludW91cyIpCgptZXJnZShzdWIyMDIzNzZfZHQsIGlwaG9wX3RheF9kdCwgYnkgPSAic3BlY2llcyIpICU+JQogIGZpbHRlcihob3N0X2dlbnVzID09ICJnX19GYWVjYWxpYmFjdGVyaXVtIikgJT4lCiAgZ3JvdXBfYnkoc3BlY2llcykgJT4lCiAgbXV0YXRlKGF2Z19hZ2UgPSBtZWFuKGFnZV9kYXlzKSkgJT4lCiAgY29tcGxldGUoYWdlX2RheXMpICU+JQogIHNlbGVjdChsaW5lYWdlLCBzcGVjaWVzLCBhZ2VfZGF5cywgc2FtcGxlSUQsIHJlbF9hYnVuZGFuY2UsIGF2Z19hZ2UpICU+JQogIG11dGF0ZShyZWxfYWJ1bmRhbmNlID0gaWZlbHNlKGlzLm5hKHJlbF9hYnVuZGFuY2UpLCAwLCByZWxfYWJ1bmRhbmNlKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGdncGxvdChhZXMoeCA9IGFnZV9kYXlzLCB5ID0gcmVsX2FidW5kYW5jZSxjb2xvciA9IHJlb3JkZXIoc3BlY2llcywgYXZnX2FnZSksIGZpbGwgPSByZW9yZGVyKHNwZWNpZXMsIGF2Z19hZ2UpKSkgKwogIGdlb21fY29sKCkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBwYWwpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gcGFsKSArCiAgZmFjZXRfd3JhcCh2YXJzKHJlb3JkZXIoc3BlY2llcywgYXZnX2FnZSkpLCAgCiAgICAgICAgICAgICBuY29sID0gMSwgc3RyaXAucG9zaXRpb24gPSAicmlnaHQiLCAKICAgICAgICAgICAgIGxhYmVsbGVyID0gbGFiZWxfd3JhcF9nZW4od2lkdGggPSAxMykpICsKICB4bGltKGMoMCwyMTAwKSkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJPZmYiLAogICAgICAgIHN0cmlwLnRleHQueS5yaWdodCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDApKQoKZ2dzYXZlKGZpbGUgPSAiL1VzZXJzL21pY2hhZWx0aXN6YS9taWtlX3Rpc3phL3NhbmRib3gvcGhhZ2VfYmFjdGVyaWFfc3BlY2lmaWNfc3ViamVjdHMvc3ViMjAyMzc2X2ZhZWNhbGlfcGhhZ2UxLnBkZiIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gOS41KQoKYGBgCgpgYGB7cn0Kc3ViMjAyMzc2X2R0ICU+JQogIGdyb3VwX2J5KHNwZWNpZXMpICU+JQogIHN1bW1hcml6ZShvYnNlcnZhdGlvbiA9IG4oKSkgJT4lCiAgYXJyYW5nZShkZXNjKG9ic2VydmF0aW9uKSkgIyU+JQogIGZpbHRlcihncmVwbCgiRGlhbGlzdGVyIiwgc3BlY2llcykpCmBgYAoKYGBge3J9CnN1YjIwMjM3Nl9kdCAlPiUKICBzZWxlY3QobGluZWFnZSwgc3BlY2llcywgYWdlX2RheXMsIHNhbXBsZUlELCByZWxfYWJ1bmRhbmNlKSAlPiUKICBjb21wbGV0ZShzcGVjaWVzLCBhZ2VfZGF5cykgJT4lCiAgZmlsdGVyKGdyZXBsKCJnX19EaWFsaXN0ZXIiLCBsaW5lYWdlKSkgJT4lCiAgbXV0YXRlKHJlbF9hYnVuZGFuY2UgPSBpZmVsc2UoaXMubmEocmVsX2FidW5kYW5jZSksIDAsIHJlbF9hYnVuZGFuY2UpKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoYXZnX2FnZSA9IG1lYW4oYWdlX2RheXMpLAogICAgICAgICBzcGVjaWVzID0gZ3N1YigiXyIsICIgIixzcGVjaWVzKSwKICAgICAgICAgc3BlY2llcyA9IGdzdWIoIlxcfHQiLCAiIixzcGVjaWVzKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gYWdlX2RheXMsIHkgPSByZWxfYWJ1bmRhbmNlLGNvbG9yID0gcmVvcmRlcihzcGVjaWVzLCBhdmdfYWdlKSwgZmlsbCA9IHJlb3JkZXIoc3BlY2llcywgYXZnX2FnZSkpKSArCiAgZ2VvbV9jb2woKSArCiAgZ2VvbV9saW5lKCkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgZmFjZXRfd3JhcCh2YXJzKHJlb3JkZXIoc3BlY2llcywgYXZnX2FnZSkpLCAgCiAgICAgICAgICAgICBuY29sID0gMSwgc3RyaXAucG9zaXRpb24gPSAicmlnaHQiLCAKICAgICAgICAgICAgIGxhYmVsbGVyID0gbGFiZWxfd3JhcF9nZW4od2lkdGggPSAxMykpICsKICB0aGVtZV9saW5lZHJhdygpICsKICB4bGltKGMoMCwyMTAwKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJPZmYiLAogICAgICAgIHN0cmlwLnRleHQueS5yaWdodCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDApKQoKZ2dzYXZlKGZpbGUgPSAiL1VzZXJzL21pY2hhZWx0aXN6YS9taWtlX3Rpc3phL3NhbmRib3gvcGhhZ2VfYmFjdGVyaWFfc3BlY2lmaWNfc3ViamVjdHMvc3ViMjAyMzc2X2RpYWxpc3Rlcl9iYWN0ZXJpYTEucGRmIiwgd2lkdGggPSA4LCBoZWlnaHQgPSAyLjgpCgpgYGAKCmBgYHtyfQoKcGFsID0gd2VzX3BhbGV0dGUoIkZhbnRhc3RpY0ZveDEiLCAxNSwgdHlwZSA9ICJjb250aW51b3VzIikKCm1lcmdlKHN1YjIwMjM3Nl9kdCwgaXBob3BfdGF4X2R0LCBieSA9ICJzcGVjaWVzIikgJT4lCiAgZmlsdGVyKGhvc3RfZ2VudXMgPT0gImdfX0RpYWxpc3RlciIpICU+JQogIGdyb3VwX2J5KHNwZWNpZXMpICU+JQogIG11dGF0ZShhdmdfYWdlID0gbWVhbihhZ2VfZGF5cykpICU+JQogIGNvbXBsZXRlKGFnZV9kYXlzKSAlPiUKICBzZWxlY3QobGluZWFnZSwgc3BlY2llcywgYWdlX2RheXMsIHNhbXBsZUlELCByZWxfYWJ1bmRhbmNlLCBhdmdfYWdlKSAlPiUKICBtdXRhdGUocmVsX2FidW5kYW5jZSA9IGlmZWxzZShpcy5uYShyZWxfYWJ1bmRhbmNlKSwgMCwgcmVsX2FidW5kYW5jZSkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBhZ2VfZGF5cywgeSA9IHJlbF9hYnVuZGFuY2UsY29sb3IgPSByZW9yZGVyKHNwZWNpZXMsIGF2Z19hZ2UpLCBmaWxsID0gcmVvcmRlcihzcGVjaWVzLCBhdmdfYWdlKSkpICsKICBnZW9tX2NvbCgpICsKICBnZW9tX2xpbmUoKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHBhbCkgKwogIGZhY2V0X3dyYXAodmFycyhyZW9yZGVyKHNwZWNpZXMsIGF2Z19hZ2UpKSwgIAogICAgICAgICAgICAgbmNvbCA9IDEsIHN0cmlwLnBvc2l0aW9uID0gInJpZ2h0IiwgCiAgICAgICAgICAgICBsYWJlbGxlciA9IGxhYmVsX3dyYXBfZ2VuKHdpZHRoID0gMTMpKSArCiAgeGxpbShjKDAsMjEwMCkpICsKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiT2ZmIiwKICAgICAgICBzdHJpcC50ZXh0LnkucmlnaHQgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwKSkKCmdnc2F2ZShmaWxlID0gIi9Vc2Vycy9taWNoYWVsdGlzemEvbWlrZV90aXN6YS9zYW5kYm94L3BoYWdlX2JhY3RlcmlhX3NwZWNpZmljX3N1YmplY3RzL3N1YjIwMjM3Nl9kaWFsaXN0ZXJfcGhhZ2UxLnBkZiIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gOS41KQoKYGBgCgpBbGlzdGlwZXMKYGBge3J9CnN1YjIwMjM3Nl9kdCAlPiUKICBzZWxlY3QobGluZWFnZSwgc3BlY2llcywgYWdlX2RheXMsIHNhbXBsZUlELCByZWxfYWJ1bmRhbmNlKSAlPiUKICBjb21wbGV0ZShzcGVjaWVzLCBhZ2VfZGF5cykgJT4lCiAgZmlsdGVyKGdyZXBsKCJnX19BbGlzdGlwZXMiLCBsaW5lYWdlKSkgJT4lCiAgbXV0YXRlKHJlbF9hYnVuZGFuY2UgPSBpZmVsc2UoaXMubmEocmVsX2FidW5kYW5jZSksIDAsIHJlbF9hYnVuZGFuY2UpKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoYXZnX2FnZSA9IG1lYW4oYWdlX2RheXMpLAogICAgICAgICBzcGVjaWVzID0gZ3N1YigiXyIsICIgIixzcGVjaWVzKSwKICAgICAgICAgc3BlY2llcyA9IGdzdWIoIlxcfHQiLCAiIixzcGVjaWVzKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gYWdlX2RheXMsIHkgPSByZWxfYWJ1bmRhbmNlLGNvbG9yID0gcmVvcmRlcihzcGVjaWVzLCBhdmdfYWdlKSwgZmlsbCA9IHJlb3JkZXIoc3BlY2llcywgYXZnX2FnZSkpKSArCiAgZ2VvbV9jb2woKSArCiAgZ2VvbV9saW5lKCkgKwogIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgc2NhbGVfY29sb3JfYnJld2VyKHBhbGV0dGUgPSAiRGFyazIiKSArCiAgZmFjZXRfd3JhcCh2YXJzKHJlb3JkZXIoc3BlY2llcywgYXZnX2FnZSkpLCAgCiAgICAgICAgICAgICBuY29sID0gMSwgc3RyaXAucG9zaXRpb24gPSAicmlnaHQiLCAKICAgICAgICAgICAgIGxhYmVsbGVyID0gbGFiZWxfd3JhcF9nZW4od2lkdGggPSAxMykpICsKICB0aGVtZV9saW5lZHJhdygpICsKICB4bGltKGMoMCwyMTAwKSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJPZmYiLAogICAgICAgIHN0cmlwLnRleHQueS5yaWdodCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDApKQoKZ2dzYXZlKGZpbGUgPSAiL1VzZXJzL21pY2hhZWx0aXN6YS9taWtlX3Rpc3phL3NhbmRib3gvcGhhZ2VfYmFjdGVyaWFfc3BlY2lmaWNfc3ViamVjdHMvc3ViMjAyMzc2X0FsaXN0aXBlc19iYWN0ZXJpYTEucGRmIiwgd2lkdGggPSA4LCBoZWlnaHQgPSAyLjgpCgpgYGAKCmBgYHtyfQoKcGFsID0gd2VzX3BhbGV0dGUoIkZhbnRhc3RpY0ZveDEiLCAxNSwgdHlwZSA9ICJjb250aW51b3VzIikKCm1lcmdlKHN1YjIwMjM3Nl9kdCwgaXBob3BfdGF4X2R0LCBieSA9ICJzcGVjaWVzIikgJT4lCiAgZmlsdGVyKGhvc3RfZ2VudXMgPT0gImdfX0FsaXN0aXBlcyIpICU+JQogIGdyb3VwX2J5KHNwZWNpZXMpICU+JQogIG11dGF0ZShhdmdfYWdlID0gbWVhbihhZ2VfZGF5cykpICU+JQogIGNvbXBsZXRlKGFnZV9kYXlzKSAlPiUKICBzZWxlY3QobGluZWFnZSwgc3BlY2llcywgYWdlX2RheXMsIHNhbXBsZUlELCByZWxfYWJ1bmRhbmNlLCBhdmdfYWdlKSAlPiUKICBtdXRhdGUocmVsX2FidW5kYW5jZSA9IGlmZWxzZShpcy5uYShyZWxfYWJ1bmRhbmNlKSwgMCwgcmVsX2FidW5kYW5jZSkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBhZ2VfZGF5cywgeSA9IHJlbF9hYnVuZGFuY2UsY29sb3IgPSByZW9yZGVyKHNwZWNpZXMsIGF2Z19hZ2UpLCBmaWxsID0gcmVvcmRlcihzcGVjaWVzLCBhdmdfYWdlKSkpICsKICBnZW9tX2NvbCgpICsKICBnZW9tX2xpbmUoKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHBhbCkgKwogIGZhY2V0X3dyYXAodmFycyhyZW9yZGVyKHNwZWNpZXMsIGF2Z19hZ2UpKSwgIAogICAgICAgICAgICAgbmNvbCA9IDEsIHN0cmlwLnBvc2l0aW9uID0gInJpZ2h0IiwgCiAgICAgICAgICAgICBsYWJlbGxlciA9IGxhYmVsX3dyYXBfZ2VuKHdpZHRoID0gMTMpKSArCiAgeGxpbShjKDAsMjEwMCkpICsKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiT2ZmIiwKICAgICAgICBzdHJpcC50ZXh0LnkucmlnaHQgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwKSkKCmdnc2F2ZShmaWxlID0gIi9Vc2Vycy9taWNoYWVsdGlzemEvbWlrZV90aXN6YS9zYW5kYm94L3BoYWdlX2JhY3RlcmlhX3NwZWNpZmljX3N1YmplY3RzL3N1YjIwMjM3Nl9BbGlzdGlwZXNfcGhhZ2UxLnBkZiIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gOS41KQoKYGBgCgoKUm9zZWJ1cmlhCmBgYHtyfQpzdWIyMDIzNzZfZHQgJT4lCiAgc2VsZWN0KGxpbmVhZ2UsIHNwZWNpZXMsIGFnZV9kYXlzLCBzYW1wbGVJRCwgcmVsX2FidW5kYW5jZSkgJT4lCiAgY29tcGxldGUoc3BlY2llcywgYWdlX2RheXMpICU+JQogIGZpbHRlcihncmVwbCgiZ19fUm9zZWJ1cmlhIiwgbGluZWFnZSkpICU+JQogIG11dGF0ZShyZWxfYWJ1bmRhbmNlID0gaWZlbHNlKGlzLm5hKHJlbF9hYnVuZGFuY2UpLCAwLCByZWxfYWJ1bmRhbmNlKSkgJT4lCiAgZ3JvdXBfYnkoc3BlY2llcykgJT4lCiAgbXV0YXRlKGF2Z19hZ2UgPSBtZWFuKGFnZV9kYXlzKSwKICAgICAgICAgc3BlY2llcyA9IGdzdWIoIl8iLCAiICIsc3BlY2llcyksCiAgICAgICAgIHNwZWNpZXMgPSBnc3ViKCJcXHx0IiwgIiIsc3BlY2llcykpICU+JQogIGdncGxvdChhZXMoeCA9IGFnZV9kYXlzLCB5ID0gcmVsX2FidW5kYW5jZSxjb2xvciA9IHJlb3JkZXIoc3BlY2llcywgYXZnX2FnZSksIGZpbGwgPSByZW9yZGVyKHNwZWNpZXMsIGF2Z19hZ2UpKSkgKwogIGdlb21fY29sKCkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikgKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIkRhcmsyIikgKwogIGZhY2V0X3dyYXAodmFycyhyZW9yZGVyKHNwZWNpZXMsIGF2Z19hZ2UpKSwgIAogICAgICAgICAgICAgbmNvbCA9IDEsIHN0cmlwLnBvc2l0aW9uID0gInJpZ2h0IiwgCiAgICAgICAgICAgICBsYWJlbGxlciA9IGxhYmVsX3dyYXBfZ2VuKHdpZHRoID0gMTMpKSArCiAgdGhlbWVfbGluZWRyYXcoKSArCiAgeGxpbShjKDAsMjEwMCkpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiT2ZmIiwKICAgICAgICBzdHJpcC50ZXh0LnkucmlnaHQgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwKSkKCmdnc2F2ZShmaWxlID0gIi9Vc2Vycy9taWNoYWVsdGlzemEvbWlrZV90aXN6YS9zYW5kYm94L3BoYWdlX2JhY3RlcmlhX3NwZWNpZmljX3N1YmplY3RzL3N1YjIwMjM3Nl9Sb3NlYnVyaWFfYmFjdGVyaWExLnBkZiIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gMi44KQoKYGBgCgpgYGB7cn0KCnBhbCA9IHdlc19wYWxldHRlKCJGYW50YXN0aWNGb3gxIiwgMTUsIHR5cGUgPSAiY29udGludW91cyIpCgptZXJnZShzdWIyMDIzNzZfZHQsIGlwaG9wX3RheF9kdCwgYnkgPSAic3BlY2llcyIpICU+JQogIGZpbHRlcihob3N0X2dlbnVzID09ICJnX19Sb3NlYnVyaWEiKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoYXZnX2FnZSA9IG1lYW4oYWdlX2RheXMpKSAlPiUKICBjb21wbGV0ZShhZ2VfZGF5cykgJT4lCiAgc2VsZWN0KGxpbmVhZ2UsIHNwZWNpZXMsIGFnZV9kYXlzLCBzYW1wbGVJRCwgcmVsX2FidW5kYW5jZSwgYXZnX2FnZSkgJT4lCiAgbXV0YXRlKHJlbF9hYnVuZGFuY2UgPSBpZmVsc2UoaXMubmEocmVsX2FidW5kYW5jZSksIDAsIHJlbF9hYnVuZGFuY2UpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gYWdlX2RheXMsIHkgPSByZWxfYWJ1bmRhbmNlLGNvbG9yID0gcmVvcmRlcihzcGVjaWVzLCBhdmdfYWdlKSwgZmlsbCA9IHJlb3JkZXIoc3BlY2llcywgYXZnX2FnZSkpKSArCiAgZ2VvbV9jb2woKSArCiAgZ2VvbV9saW5lKCkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhbCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBwYWwpICsKICBmYWNldF93cmFwKHZhcnMocmVvcmRlcihzcGVjaWVzLCBhdmdfYWdlKSksICAKICAgICAgICAgICAgIG5jb2wgPSAxLCBzdHJpcC5wb3NpdGlvbiA9ICJyaWdodCIsIAogICAgICAgICAgICAgbGFiZWxsZXIgPSBsYWJlbF93cmFwX2dlbih3aWR0aCA9IDEzKSkgKwogIHhsaW0oYygwLDIxMDApKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIk9mZiIsCiAgICAgICAgc3RyaXAudGV4dC55LnJpZ2h0ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCkpCgpnZ3NhdmUoZmlsZSA9ICIvVXNlcnMvbWljaGFlbHRpc3phL21pa2VfdGlzemEvc2FuZGJveC9waGFnZV9iYWN0ZXJpYV9zcGVjaWZpY19zdWJqZWN0cy9zdWIyMDIzNzZfUm9zZWJ1cmlhX3BoYWdlMS5wZGYiLCB3aWR0aCA9IDgsIGhlaWdodCA9IDkuNSkKCmBgYAoKMjAyMzc2IHRpbGVtYXAKYGBge3J9CmJhY19mcF9zdWIyMDIzNzYgPC0gc3ViMjAyMzc2X2R0ICU+JQogIHNlbGVjdChsaW5lYWdlLCBzcGVjaWVzLCBhZ2VfZGF5cywgc2FtcGxlSUQsIHJlbF9hYnVuZGFuY2UpICU+JQogIGNvbXBsZXRlKHNwZWNpZXMsIGFnZV9kYXlzKSAlPiUKICBmaWx0ZXIoZ3JlcGwoImdfX0ZhZWNhbGliYWN0ZXJpdW0iLCBsaW5lYWdlKSkgJT4lCiAgbXV0YXRlKHJlbF9hYnVuZGFuY2UgPSBpZmVsc2UoaXMubmEocmVsX2FidW5kYW5jZSksIDAsIHJlbF9hYnVuZGFuY2UpKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoYXZnX2FnZSA9IG1lYW4oYWdlX2RheXMpLAogICAgICAgICBzcGVjaWVzID0gZ3N1YigiXyIsICIgIixzcGVjaWVzKSwKICAgICAgICAgc3BlY2llcyA9IGdzdWIoIlxcfHQiLCAiIixzcGVjaWVzKSkgJT4lCiAgdW5ncm91cCgpCgpiYWNfZnBfc3ViMjAyMzc2JGtpbmdkb20gPC0gIkJhY3RlcmlhIgoKcGhhZ2VfZnBfc3ViMjAyMzc2IDwtIG1lcmdlKHN1YjIwMjM3Nl9kdCwgaXBob3BfdGF4X2R0LCBieSA9ICJzcGVjaWVzIikgJT4lCiAgZmlsdGVyKGhvc3RfZ2VudXMgPT0gImdfX0ZhZWNhbGliYWN0ZXJpdW0iKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoYXZnX2FnZSA9IG1lYW4oYWdlX2RheXMpKSAlPiUKICBjb21wbGV0ZShhZ2VfZGF5cykgJT4lCiAgc2VsZWN0KGxpbmVhZ2UsIHNwZWNpZXMsIGFnZV9kYXlzLCBzYW1wbGVJRCwgcmVsX2FidW5kYW5jZSwgYXZnX2FnZSkgJT4lCiAgbXV0YXRlKHJlbF9hYnVuZGFuY2UgPSBpZmVsc2UoaXMubmEocmVsX2FidW5kYW5jZSksIDAsIHJlbF9hYnVuZGFuY2UpKSAlPiUKICB1bmdyb3VwKCkKCnBoYWdlX2ZwX3N1YjIwMjM3NiRraW5nZG9tIDwtICJWaXJ1cyIKCnN1YjIwMjM3Nl9mcF9hbGxfZHQgPC0gcmJpbmQoYmFjX2ZwX3N1YjIwMjM3NiwgcGhhZ2VfZnBfc3ViMjAyMzc2KQoKYGBgCgpgYGB7cn0KdGVtcHAgPC0gc3ViMjAyMzc2X2ZwX2FsbF9kdCAlPiUKICBtdXRhdGUoc3BlY2llcyA9IGdzdWIoIkZhZWNhbGliYWN0ZXJpdW0iLCAiRiIsIHNwZWNpZXMpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBmYWN0b3IoYWdlX2RheXMpLCB5ID0gcmVvcmRlcihzcGVjaWVzLCBkZXNjKGF2Z19hZ2UpKSwgCiAgICAgICAgICAgICBjb2xvciA9IGtpbmdkb20sIHNpemUgPSByZWxfYWJ1bmRhbmNlKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjgpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygib3JhbmdlcmVkIiwgImNhZGV0Ymx1ZSIpKSArCiAgc2NhbGVfc2l6ZShuYW1lID0gInJlbC5cbmFidW5kYW5jZSIpICsgIAogIGZhY2V0X2dyaWQodmFycyhraW5nZG9tKSwgc2NhbGVzID0gImZyZWVfeSIsIHNwYWNlPSJmcmVlIikgKwogIHRoZW1lX2J3KCkgKwogIGxhYnMoeSA9ICJTR0IiLCB4ID0gImRheSBvZiBsaWZlIikgKwogIHRoZW1lKHN0cmlwLnRleHQueS5yaWdodCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDApLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdD0xKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibGVmdCIpCgpkZXRlY3RwIDwtIHN1YjIwMjM3Nl9mcF9hbGxfZHQgJT4lCiAgZ3JvdXBfYnkoc3BlY2llcywga2luZ2RvbSwgYXZnX2FnZSkgJT4lCiAgc3VtbWFyaXplKGRldGVjdGVkID0gbigpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBkZXRlY3RlZCwgeSA9IHJlb3JkZXIoc3BlY2llcywgZGVzYyhhdmdfYWdlKSkpKSArCiAgZ2VvbV9jb2woKSArCiAgZmFjZXRfZ3JpZCh2YXJzKGtpbmdkb20pLCBzY2FsZXMgPSAiZnJlZV95Iiwgc3BhY2U9ImZyZWUiKSArCiAgdGhlbWVfYncoKSArCiAgbGFicyh5ID0gIiIsIHggPSAiIyB0aW1lc1xuZGV0ZWN0ZWQiKSArCiAgdGhlbWUoc3RyaXAudGV4dC55LnJpZ2h0ID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdD0xKSwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSkKCmNvbWJwIDwtIHBsb3RfZ3JpZCh0ZW1wcCwgZGV0ZWN0cCwgYWxpZ24gPSAiaCIsIGF4aXMgPSAiYiIsIHJlbF93aWR0aHMgPSBjKDIwLCAzKSkKCmNvbWJwCmBgYAoKCmNoZWNrIG1vc3QgcHJldmFsZW50IGJhY3RlcmlhIHdpdGggZmV3IG90aGVyIFNHQnMgaW4gZ2VudXMKYGBge3J9CnN1YjIwMjM3Nl9kdCAlPiUgCiAgZmlsdGVyKGtpbmdkb20gPT0gIkJhY3RlcmlhIikgJT4lCiAgbXV0YXRlKGdlbnVzID0gZ3N1YigiXFx8c19fLioiLCAiIiwgbGluZWFnZSksCiAgICAgICAgIGdlbnVzID0gZ3N1YigiLipcXHxnX18iLCAiIiwgZ2VudXMpKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoZGV0ZWN0ZWQgPSBuKCkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBncm91cF9ieShnZW51cykgJT4lCiAgbXV0YXRlKGRpc3RpbmN0X2cgPSBuX2Rpc3RpbmN0KHNwZWNpZXMpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZGlzdGluY3QoZ2VudXMsIHNwZWNpZXMsIGRldGVjdGVkLCBkaXN0aW5jdF9nKSAlPiUKICBhcnJhbmdlKGRpc3RpbmN0X2csIGRlc2MoZGV0ZWN0ZWQpKQpgYGAKCjIwMjM3NiB0aWxlbWFwCmBgYHtyfQpiYWNfZnBfc3ViMjAyMzc2IDwtIHN1YjIwMjM3Nl9kdCAlPiUKICBzZWxlY3QobGluZWFnZSwgc3BlY2llcywgYWdlX2RheXMsIHNhbXBsZUlELCByZWxfYWJ1bmRhbmNlKSAlPiUKICBjb21wbGV0ZShzcGVjaWVzLCBhZ2VfZGF5cykgJT4lCiAgZmlsdGVyKGdyZXBsKCJnX19GbGF2b25pZnJhY3RvciIsIGxpbmVhZ2UpKSAlPiUKICBtdXRhdGUocmVsX2FidW5kYW5jZSA9IGlmZWxzZShpcy5uYShyZWxfYWJ1bmRhbmNlKSwgMCwgcmVsX2FidW5kYW5jZSkpICU+JQogIGdyb3VwX2J5KHNwZWNpZXMpICU+JQogIG11dGF0ZShhdmdfYWdlID0gbWVhbihhZ2VfZGF5cyksCiAgICAgICAgIHNwZWNpZXMgPSBnc3ViKCJfIiwgIiAiLHNwZWNpZXMpLAogICAgICAgICBzcGVjaWVzID0gZ3N1YigiXFx8dCIsICIiLHNwZWNpZXMpKSAlPiUKICB1bmdyb3VwKCkKCmJhY19mcF9zdWIyMDIzNzYka2luZ2RvbSA8LSAiQmFjdGVyaWEiCgpwaGFnZV9mcF9zdWIyMDIzNzYgPC0gbWVyZ2Uoc3ViMjAyMzc2X2R0LCBpcGhvcF90YXhfZHQsIGJ5ID0gInNwZWNpZXMiKSAlPiUKICBmaWx0ZXIoaG9zdF9nZW51cyA9PSAiZ19fRmxhdm9uaWZyYWN0b3IiKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoYXZnX2FnZSA9IG1lYW4oYWdlX2RheXMpKSAlPiUKICBjb21wbGV0ZShhZ2VfZGF5cykgJT4lCiAgc2VsZWN0KGxpbmVhZ2UsIHNwZWNpZXMsIGFnZV9kYXlzLCBzYW1wbGVJRCwgcmVsX2FidW5kYW5jZSwgYXZnX2FnZSkgJT4lCiAgbXV0YXRlKHJlbF9hYnVuZGFuY2UgPSBpZmVsc2UoaXMubmEocmVsX2FidW5kYW5jZSksIDAsIHJlbF9hYnVuZGFuY2UpKSAlPiUKICB1bmdyb3VwKCkKCnBoYWdlX2ZwX3N1YjIwMjM3NiRraW5nZG9tIDwtICJWaXJ1cyIKCnN1YjIwMjM3Nl9mcF9hbGxfZHQgPC0gcmJpbmQoYmFjX2ZwX3N1YjIwMjM3NiwgcGhhZ2VfZnBfc3ViMjAyMzc2KQoKYGBgCgpgYGB7cn0KdGVtcHAgPC0gc3ViMjAyMzc2X2ZwX2FsbF9kdCAlPiUKICBtdXRhdGUoc3BlY2llcyA9IGdzdWIoIkZsYXZvbmlmcmFjdG9yIiwgIkYiLCBzcGVjaWVzKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZmFjdG9yKGFnZV9kYXlzKSwgeSA9IHJlb3JkZXIoc3BlY2llcywgZGVzYyhhdmdfYWdlKSksIAogICAgICAgICAgICAgY29sb3IgPSBraW5nZG9tLCBzaXplID0gcmVsX2FidW5kYW5jZSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC44KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIm9yYW5nZXJlZCIsICJjYWRldGJsdWUiKSkgKwogIHNjYWxlX3NpemUobmFtZSA9ICJyZWwuXG5hYnVuZGFuY2UiKSArICAKICBmYWNldF9ncmlkKHZhcnMoa2luZ2RvbSksIHNjYWxlcyA9ICJmcmVlX3kiLCBzcGFjZT0iZnJlZSIpICsKICB0aGVtZV9idygpICsKICBsYWJzKHkgPSAiU0dCIiwgeCA9ICJkYXkgb2YgbGlmZSIpICsKICB0aGVtZShzdHJpcC50ZXh0LnkucmlnaHQgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImxlZnQiKQoKZGV0ZWN0cCA8LSBzdWIyMDIzNzZfZnBfYWxsX2R0ICU+JQogIGdyb3VwX2J5KHNwZWNpZXMsIGtpbmdkb20sIGF2Z19hZ2UpICU+JQogIHN1bW1hcml6ZShkZXRlY3RlZCA9IG4oKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGV0ZWN0ZWQsIHkgPSByZW9yZGVyKHNwZWNpZXMsIGRlc2MoYXZnX2FnZSkpKSkgKwogIGdlb21fY29sKCkgKwogIGZhY2V0X2dyaWQodmFycyhraW5nZG9tKSwgc2NhbGVzID0gImZyZWVfeSIsIHNwYWNlPSJmcmVlIikgKwogIHRoZW1lX2J3KCkgKwogIGxhYnMoeSA9ICIiLCB4ID0gIiMgdGltZXNcbmRldGVjdGVkIikgKwogIHRoZW1lKHN0cmlwLnRleHQueS5yaWdodCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCkpCgpjb21icCA8LSBwbG90X2dyaWQodGVtcHAsIGRldGVjdHAsIGFsaWduID0gImgiLCBheGlzID0gImIiLCByZWxfd2lkdGhzID0gYygyMCwgMykpCgpjb21icApgYGAKCjIwMjM3NiB0aWxlbWFwCmBgYHtyfQpiYWNfZnBfc3ViMjAyMzc2IDwtIHN1YjIwMjM3Nl9kdCAlPiUKICBzZWxlY3QobGluZWFnZSwgc3BlY2llcywgYWdlX2RheXMsIHNhbXBsZUlELCByZWxfYWJ1bmRhbmNlKSAlPiUKICBjb21wbGV0ZShzcGVjaWVzLCBhZ2VfZGF5cykgJT4lCiAgZmlsdGVyKGdyZXBsKCJnX19Fc2NoZXJpY2hpYSIsIGxpbmVhZ2UpKSAlPiUKICBtdXRhdGUocmVsX2FidW5kYW5jZSA9IGlmZWxzZShpcy5uYShyZWxfYWJ1bmRhbmNlKSwgMCwgcmVsX2FidW5kYW5jZSkpICU+JQogIGdyb3VwX2J5KHNwZWNpZXMpICU+JQogIG11dGF0ZShhdmdfYWdlID0gbWVhbihhZ2VfZGF5cyksCiAgICAgICAgIHNwZWNpZXMgPSBnc3ViKCJfIiwgIiAiLHNwZWNpZXMpLAogICAgICAgICBzcGVjaWVzID0gZ3N1YigiXFx8dCIsICIiLHNwZWNpZXMpKSAlPiUKICB1bmdyb3VwKCkKCmJhY19mcF9zdWIyMDIzNzYka2luZ2RvbSA8LSAiQmFjdGVyaWEiCgpwaGFnZV9mcF9zdWIyMDIzNzYgPC0gbWVyZ2Uoc3ViMjAyMzc2X2R0LCBpcGhvcF90YXhfZHQsIGJ5ID0gInNwZWNpZXMiKSAlPiUKICBmaWx0ZXIoaG9zdF9nZW51cyA9PSAiZ19fRXNjaGVyaWNoaWEiKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoYXZnX2FnZSA9IG1lYW4oYWdlX2RheXMpKSAlPiUKICBjb21wbGV0ZShhZ2VfZGF5cykgJT4lCiAgc2VsZWN0KGxpbmVhZ2UsIHNwZWNpZXMsIGFnZV9kYXlzLCBzYW1wbGVJRCwgcmVsX2FidW5kYW5jZSwgYXZnX2FnZSkgJT4lCiAgbXV0YXRlKHJlbF9hYnVuZGFuY2UgPSBpZmVsc2UoaXMubmEocmVsX2FidW5kYW5jZSksIDAsIHJlbF9hYnVuZGFuY2UpKSAlPiUKICB1bmdyb3VwKCkKCnBoYWdlX2ZwX3N1YjIwMjM3NiRraW5nZG9tIDwtICJWaXJ1cyIKCnN1YjIwMjM3Nl9mcF9hbGxfZHQgPC0gcmJpbmQoYmFjX2ZwX3N1YjIwMjM3NiwgcGhhZ2VfZnBfc3ViMjAyMzc2KQoKYGBgCgpgYGB7cn0KdGVtcHAgPC0gc3ViMjAyMzc2X2ZwX2FsbF9kdCAlPiUKICBtdXRhdGUoc3BlY2llcyA9IGdzdWIoIkVzY2hlcmljaGlhIiwgIkUiLCBzcGVjaWVzKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZmFjdG9yKGFnZV9kYXlzKSwgeSA9IHJlb3JkZXIoc3BlY2llcywgZGVzYyhhdmdfYWdlKSksIAogICAgICAgICAgICAgY29sb3IgPSBraW5nZG9tLCBzaXplID0gcmVsX2FidW5kYW5jZSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC44KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIm9yYW5nZXJlZCIsICJjYWRldGJsdWUiKSkgKwogIHNjYWxlX3NpemUobmFtZSA9ICJyZWwuXG5hYnVuZGFuY2UiKSArICAKICBmYWNldF9ncmlkKHZhcnMoa2luZ2RvbSksIHNjYWxlcyA9ICJmcmVlX3kiLCBzcGFjZT0iZnJlZSIpICsKICB0aGVtZV9idygpICsKICBsYWJzKHkgPSAiU0dCIiwgeCA9ICJkYXkgb2YgbGlmZSIpICsKICB0aGVtZShzdHJpcC50ZXh0LnkucmlnaHQgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImxlZnQiKQoKZGV0ZWN0cCA8LSBzdWIyMDIzNzZfZnBfYWxsX2R0ICU+JQogIGdyb3VwX2J5KHNwZWNpZXMsIGtpbmdkb20sIGF2Z19hZ2UpICU+JQogIHN1bW1hcml6ZShkZXRlY3RlZCA9IG4oKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGV0ZWN0ZWQsIHkgPSByZW9yZGVyKHNwZWNpZXMsIGRlc2MoYXZnX2FnZSkpKSkgKwogIGdlb21fY29sKCkgKwogIGZhY2V0X2dyaWQodmFycyhraW5nZG9tKSwgc2NhbGVzID0gImZyZWVfeSIsIHNwYWNlPSJmcmVlIikgKwogIHRoZW1lX2J3KCkgKwogIGxhYnMoeSA9ICIiLCB4ID0gIiMgdGltZXNcbmRldGVjdGVkIikgKwogIHRoZW1lKHN0cmlwLnRleHQueS5yaWdodCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCkpCgpjb21icCA8LSBwbG90X2dyaWQodGVtcHAsIGRldGVjdHAsIGFsaWduID0gImgiLCBheGlzID0gImIiLCByZWxfd2lkdGhzID0gYygyMCwgMykpCgpjb21icApgYGAKCjIwMjM3NiB0aWxlbWFwCmBgYHtyfQpiYWNfZnBfc3ViMjAyMzc2IDwtIHN1YjIwMjM3Nl9kdCAlPiUKICBzZWxlY3QobGluZWFnZSwgc3BlY2llcywgYWdlX2RheXMsIHNhbXBsZUlELCByZWxfYWJ1bmRhbmNlKSAlPiUKICBjb21wbGV0ZShzcGVjaWVzLCBhZ2VfZGF5cykgJT4lCiAgZmlsdGVyKGdyZXBsKCJnX19CYXJuZXNpZWxsYSIsIGxpbmVhZ2UpKSAlPiUKICBtdXRhdGUocmVsX2FidW5kYW5jZSA9IGlmZWxzZShpcy5uYShyZWxfYWJ1bmRhbmNlKSwgMCwgcmVsX2FidW5kYW5jZSkpICU+JQogIGdyb3VwX2J5KHNwZWNpZXMpICU+JQogIG11dGF0ZShhdmdfYWdlID0gbWVhbihhZ2VfZGF5cyksCiAgICAgICAgIHNwZWNpZXMgPSBnc3ViKCJfIiwgIiAiLHNwZWNpZXMpLAogICAgICAgICBzcGVjaWVzID0gZ3N1YigiXFx8dCIsICIiLHNwZWNpZXMpKSAlPiUKICB1bmdyb3VwKCkKCmJhY19mcF9zdWIyMDIzNzYka2luZ2RvbSA8LSAiQmFjdGVyaWEiCgpwaGFnZV9mcF9zdWIyMDIzNzYgPC0gbWVyZ2Uoc3ViMjAyMzc2X2R0LCBpcGhvcF90YXhfZHQsIGJ5ID0gInNwZWNpZXMiKSAlPiUKICBmaWx0ZXIoaG9zdF9nZW51cyA9PSAiZ19fQmFybmVzaWVsbGEiKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoYXZnX2FnZSA9IG1lYW4oYWdlX2RheXMpKSAlPiUKICBjb21wbGV0ZShhZ2VfZGF5cykgJT4lCiAgc2VsZWN0KGxpbmVhZ2UsIHNwZWNpZXMsIGFnZV9kYXlzLCBzYW1wbGVJRCwgcmVsX2FidW5kYW5jZSwgYXZnX2FnZSkgJT4lCiAgbXV0YXRlKHJlbF9hYnVuZGFuY2UgPSBpZmVsc2UoaXMubmEocmVsX2FidW5kYW5jZSksIDAsIHJlbF9hYnVuZGFuY2UpKSAlPiUKICB1bmdyb3VwKCkKCnBoYWdlX2ZwX3N1YjIwMjM3NiRraW5nZG9tIDwtICJWaXJ1cyIKCnN1YjIwMjM3Nl9mcF9hbGxfZHQgPC0gcmJpbmQoYmFjX2ZwX3N1YjIwMjM3NiwgcGhhZ2VfZnBfc3ViMjAyMzc2KQoKYGBgCgpgYGB7cn0KdGVtcHAgPC0gc3ViMjAyMzc2X2ZwX2FsbF9kdCAlPiUKICBtdXRhdGUoc3BlY2llcyA9IGdzdWIoIkJhcm5lc2llbGxhIiwgIkIiLCBzcGVjaWVzKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZmFjdG9yKGFnZV9kYXlzKSwgeSA9IHJlb3JkZXIoc3BlY2llcywgZGVzYyhhdmdfYWdlKSksIAogICAgICAgICAgICAgY29sb3IgPSBraW5nZG9tLCBzaXplID0gcmVsX2FidW5kYW5jZSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC44KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIm9yYW5nZXJlZCIsICJjYWRldGJsdWUiKSkgKwogIHNjYWxlX3NpemUobmFtZSA9ICJyZWwuXG5hYnVuZGFuY2UiKSArICAKICBmYWNldF9ncmlkKHZhcnMoa2luZ2RvbSksIHNjYWxlcyA9ICJmcmVlX3kiLCBzcGFjZT0iZnJlZSIpICsKICB0aGVtZV9idygpICsKICBsYWJzKHkgPSAiU0dCIiwgeCA9ICJkYXkgb2YgbGlmZSIpICsKICB0aGVtZShzdHJpcC50ZXh0LnkucmlnaHQgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImxlZnQiKQoKZGV0ZWN0cCA8LSBzdWIyMDIzNzZfZnBfYWxsX2R0ICU+JQogIGdyb3VwX2J5KHNwZWNpZXMsIGtpbmdkb20sIGF2Z19hZ2UpICU+JQogIHN1bW1hcml6ZShkZXRlY3RlZCA9IG4oKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGV0ZWN0ZWQsIHkgPSByZW9yZGVyKHNwZWNpZXMsIGRlc2MoYXZnX2FnZSkpKSkgKwogIGdlb21fY29sKCkgKwogIGZhY2V0X2dyaWQodmFycyhraW5nZG9tKSwgc2NhbGVzID0gImZyZWVfeSIsIHNwYWNlPSJmcmVlIikgKwogIHRoZW1lX2J3KCkgKwogIGxhYnMoeSA9ICIiLCB4ID0gIiMgdGltZXNcbmRldGVjdGVkIikgKwogIHRoZW1lKHN0cmlwLnRleHQueS5yaWdodCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCkpCgpjb21icCA8LSBwbG90X2dyaWQodGVtcHAsIGRldGVjdHAsIGFsaWduID0gImgiLCBheGlzID0gImIiLCByZWxfd2lkdGhzID0gYygyMCwgMykpCgpjb21icApgYGAKClBhcmFiYWN0ZXJvaWRlcwoyMDIzNzYgdGlsZW1hcApgYGB7cn0KYmFjX2ZwX3N1YjIwMjM3NiA8LSBzdWIyMDIzNzZfZHQgJT4lCiAgc2VsZWN0KGxpbmVhZ2UsIHNwZWNpZXMsIGFnZV9kYXlzLCBzYW1wbGVJRCwgcmVsX2FidW5kYW5jZSkgJT4lCiAgY29tcGxldGUoc3BlY2llcywgYWdlX2RheXMpICU+JQogIGZpbHRlcihncmVwbCgiZ19fUGFyYWJhY3Rlcm9pZGVzIiwgbGluZWFnZSkpICU+JQogIG11dGF0ZShyZWxfYWJ1bmRhbmNlID0gaWZlbHNlKGlzLm5hKHJlbF9hYnVuZGFuY2UpLCAwLCByZWxfYWJ1bmRhbmNlKSkgJT4lCiAgZ3JvdXBfYnkoc3BlY2llcykgJT4lCiAgbXV0YXRlKGF2Z19hZ2UgPSBtZWFuKGFnZV9kYXlzKSwKICAgICAgICAgc3BlY2llcyA9IGdzdWIoIl8iLCAiICIsc3BlY2llcyksCiAgICAgICAgIHNwZWNpZXMgPSBnc3ViKCJcXHx0IiwgIiIsc3BlY2llcykpICU+JQogIHVuZ3JvdXAoKQoKYmFjX2ZwX3N1YjIwMjM3NiRraW5nZG9tIDwtICJCYWN0ZXJpYSIKCnBoYWdlX2ZwX3N1YjIwMjM3NiA8LSBtZXJnZShzdWIyMDIzNzZfZHQsIGlwaG9wX3RheF9kdCwgYnkgPSAic3BlY2llcyIpICU+JQogIGZpbHRlcihob3N0X2dlbnVzID09ICJnX19QYXJhYmFjdGVyb2lkZXMiKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoYXZnX2FnZSA9IG1lYW4oYWdlX2RheXMpKSAlPiUKICBjb21wbGV0ZShhZ2VfZGF5cykgJT4lCiAgc2VsZWN0KGxpbmVhZ2UsIHNwZWNpZXMsIGFnZV9kYXlzLCBzYW1wbGVJRCwgcmVsX2FidW5kYW5jZSwgYXZnX2FnZSkgJT4lCiAgbXV0YXRlKHJlbF9hYnVuZGFuY2UgPSBpZmVsc2UoaXMubmEocmVsX2FidW5kYW5jZSksIDAsIHJlbF9hYnVuZGFuY2UpKSAlPiUKICB1bmdyb3VwKCkKCnBoYWdlX2ZwX3N1YjIwMjM3NiRraW5nZG9tIDwtICJWaXJ1cyIKCnN1YjIwMjM3Nl9mcF9hbGxfZHQgPC0gcmJpbmQoYmFjX2ZwX3N1YjIwMjM3NiwgcGhhZ2VfZnBfc3ViMjAyMzc2KQoKYGBgCgpgYGB7cn0KdGVtcHAgPC0gc3ViMjAyMzc2X2ZwX2FsbF9kdCAlPiUKICBtdXRhdGUoc3BlY2llcyA9IGdzdWIoIlBhcmFiYWN0ZXJvaWRlcyIsICJQIiwgc3BlY2llcykpICU+JQogIGdncGxvdChhZXMoeCA9IGZhY3RvcihhZ2VfZGF5cyksIHkgPSByZW9yZGVyKHNwZWNpZXMsIGRlc2MoYXZnX2FnZSkpLCAKICAgICAgICAgICAgIGNvbG9yID0ga2luZ2RvbSwgc2l6ZSA9IHJlbF9hYnVuZGFuY2UpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuOCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJvcmFuZ2VyZWQiLCAiY2FkZXRibHVlIikpICsKICBzY2FsZV9zaXplKG5hbWUgPSAicmVsLlxuYWJ1bmRhbmNlIikgKyAgCiAgZmFjZXRfZ3JpZCh2YXJzKGtpbmdkb20pLCBzY2FsZXMgPSAiZnJlZV95Iiwgc3BhY2U9ImZyZWUiKSArCiAgdGhlbWVfYncoKSArCiAgbGFicyh5ID0gIlNHQiIsIHggPSAiZGF5IG9mIGxpZmUiKSArCiAgdGhlbWUoc3RyaXAudGV4dC55LnJpZ2h0ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJsZWZ0IikKCmRldGVjdHAgPC0gc3ViMjAyMzc2X2ZwX2FsbF9kdCAlPiUKICBncm91cF9ieShzcGVjaWVzLCBraW5nZG9tLCBhdmdfYWdlKSAlPiUKICBzdW1tYXJpemUoZGV0ZWN0ZWQgPSBuKCkpICU+JQogIGdncGxvdChhZXMoeCA9IGRldGVjdGVkLCB5ID0gcmVvcmRlcihzcGVjaWVzLCBkZXNjKGF2Z19hZ2UpKSkpICsKICBnZW9tX2NvbCgpICsKICBmYWNldF9ncmlkKHZhcnMoa2luZ2RvbSksIHNjYWxlcyA9ICJmcmVlX3kiLCBzcGFjZT0iZnJlZSIpICsKICB0aGVtZV9idygpICsKICBsYWJzKHkgPSAiIiwgeCA9ICIjIHRpbWVzXG5kZXRlY3RlZCIpICsKICB0aGVtZShzdHJpcC50ZXh0LnkucmlnaHQgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpKQoKY29tYnAgPC0gcGxvdF9ncmlkKHRlbXBwLCBkZXRlY3RwLCBhbGlnbiA9ICJoIiwgYXhpcyA9ICJiIiwgcmVsX3dpZHRocyA9IGMoMjAsIDMpKQoKY29tYnAKYGBgCgoKQmFjdGVyb2lkZXMKMjAyMzc2IHRpbGVtYXAKYGBge3J9CmJhY19mcF9zdWIyMDIzNzYgPC0gc3ViMjAyMzc2X2R0ICU+JQogIHNlbGVjdChsaW5lYWdlLCBzcGVjaWVzLCBhZ2VfZGF5cywgc2FtcGxlSUQsIHJlbF9hYnVuZGFuY2UpICU+JQogIGNvbXBsZXRlKHNwZWNpZXMsIGFnZV9kYXlzKSAlPiUKICBmaWx0ZXIoZ3JlcGwoImdfX0JsYXV0aWEiLCBsaW5lYWdlKSkgJT4lCiAgbXV0YXRlKHJlbF9hYnVuZGFuY2UgPSBpZmVsc2UoaXMubmEocmVsX2FidW5kYW5jZSksIDAsIHJlbF9hYnVuZGFuY2UpKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoYXZnX2FnZSA9IG1lYW4oYWdlX2RheXMpLAogICAgICAgICBzcGVjaWVzID0gZ3N1YigiXyIsICIgIixzcGVjaWVzKSwKICAgICAgICAgc3BlY2llcyA9IGdzdWIoIlxcfHQiLCAiIixzcGVjaWVzKSkgJT4lCiAgdW5ncm91cCgpCgpiYWNfZnBfc3ViMjAyMzc2JGtpbmdkb20gPC0gIkJhY3RlcmlhIgoKcGhhZ2VfZnBfc3ViMjAyMzc2IDwtIG1lcmdlKHN1YjIwMjM3Nl9kdCwgaXBob3BfdGF4X2R0LCBieSA9ICJzcGVjaWVzIikgJT4lCiAgZmlsdGVyKGhvc3RfZ2VudXMgPT0gImdfX0JsYXV0aWEiKSAlPiUKICBncm91cF9ieShzcGVjaWVzKSAlPiUKICBtdXRhdGUoYXZnX2FnZSA9IG1lYW4oYWdlX2RheXMpKSAlPiUKICBjb21wbGV0ZShhZ2VfZGF5cykgJT4lCiAgc2VsZWN0KGxpbmVhZ2UsIHNwZWNpZXMsIGFnZV9kYXlzLCBzYW1wbGVJRCwgcmVsX2FidW5kYW5jZSwgYXZnX2FnZSkgJT4lCiAgbXV0YXRlKHJlbF9hYnVuZGFuY2UgPSBpZmVsc2UoaXMubmEocmVsX2FidW5kYW5jZSksIDAsIHJlbF9hYnVuZGFuY2UpKSAlPiUKICB1bmdyb3VwKCkKCnBoYWdlX2ZwX3N1YjIwMjM3NiRraW5nZG9tIDwtICJWaXJ1cyIKCnN1YjIwMjM3Nl9mcF9hbGxfZHQgPC0gcmJpbmQoYmFjX2ZwX3N1YjIwMjM3NiwgcGhhZ2VfZnBfc3ViMjAyMzc2KQoKYGBgCgpgYGB7cn0KdGVtcHAgPC0gc3ViMjAyMzc2X2ZwX2FsbF9kdCAlPiUKICBtdXRhdGUoc3BlY2llcyA9IGdzdWIoIlZlaWxsb25lbGxhIiwgIlYiLCBzcGVjaWVzKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZmFjdG9yKGFnZV9kYXlzKSwgeSA9IHJlb3JkZXIoc3BlY2llcywgZGVzYyhhdmdfYWdlKSksIAogICAgICAgICAgICAgY29sb3IgPSBraW5nZG9tLCBzaXplID0gcmVsX2FidW5kYW5jZSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC44KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIm9yYW5nZXJlZCIsICJjYWRldGJsdWUiKSkgKwogIHNjYWxlX3NpemUobmFtZSA9ICJyZWwuXG5hYnVuZGFuY2UiKSArICAKICBmYWNldF9ncmlkKHZhcnMoa2luZ2RvbSksIHNjYWxlcyA9ICJmcmVlX3kiLCBzcGFjZT0iZnJlZSIpICsKICB0aGVtZV9idygpICsKICBsYWJzKHkgPSAiU0dCIiwgeCA9ICJkYXkgb2YgbGlmZSIpICsKICB0aGVtZShzdHJpcC50ZXh0LnkucmlnaHQgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImxlZnQiKQoKZGV0ZWN0cCA8LSBzdWIyMDIzNzZfZnBfYWxsX2R0ICU+JQogIGdyb3VwX2J5KHNwZWNpZXMsIGtpbmdkb20sIGF2Z19hZ2UpICU+JQogIHN1bW1hcml6ZShkZXRlY3RlZCA9IG4oKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGV0ZWN0ZWQsIHkgPSByZW9yZGVyKHNwZWNpZXMsIGRlc2MoYXZnX2FnZSkpKSkgKwogIGdlb21fY29sKCkgKwogIGZhY2V0X2dyaWQodmFycyhraW5nZG9tKSwgc2NhbGVzID0gImZyZWVfeSIsIHNwYWNlPSJmcmVlIikgKwogIHRoZW1lX2J3KCkgKwogIGxhYnMoeSA9ICIiLCB4ID0gIiMgdGltZXNcbmRldGVjdGVkIikgKwogIHRoZW1lKHN0cmlwLnRleHQueS5yaWdodCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCkpCgpjb21icCA8LSBwbG90X2dyaWQodGVtcHAsIGRldGVjdHAsIGFsaWduID0gImgiLCBheGlzID0gImIiLCByZWxfd2lkdGhzID0gYygyMCwgMykpCgpjb21icApgYGAKCg==